diff --git a/Solutions/Azure Activity/Analytic Rules/Creation_of_Expensive_Computes_in_Azure.yaml b/Solutions/Azure Activity/Analytic Rules/Creation_of_Expensive_Computes_in_Azure.yaml index 2e369f4deca..fa031d01688 100644 --- a/Solutions/Azure Activity/Analytic Rules/Creation_of_Expensive_Computes_in_Azure.yaml +++ b/Solutions/Azure Activity/Analytic Rules/Creation_of_Expensive_Computes_in_Azure.yaml @@ -20,7 +20,7 @@ tactics: relevantTechniques: - T1578 query: | - let tokens = dynamic(["416","208","192","128","120","96","80","72","64","48","44","40","g5","gs5","g4","gs4","nc12","nc24","nv24"]); + let tokens = dynamic(["416","208","192","128","120","96","80","72","64","48","44","40","nc12","nc24","nv24"]); let operationList = dynamic(["microsoft.compute/virtualmachines/write", "microsoft.resources/deployments/write"]); AzureActivity | where OperationNameValue in~ (operationList) @@ -28,7 +28,7 @@ query: | | where Properties has 'vmSize' | extend parsed_property= parse_json(tostring((parse_json(Properties).responseBody))).properties | extend vmSize = tostring((parsed_property.hardwareProfile).vmSize) - | where vmSize has_any (tokens) + | mv-apply token=tokens to typeof(string) on (where vmSize contains token) | extend ComputerName = tostring((parsed_property.osProfile).computerName) | project TimeGenerated, OperationNameValue, ActivityStatusValue, Caller, CallerIpAddress, ComputerName, vmSize | extend Name = tostring(split(Caller,'@',0)[0]), UPNSuffix = tostring(split(Caller,'@',1)[0]) @@ -39,9 +39,13 @@ entityMappings: columnName: Name - identifier: UPNSuffix columnName: UPNSuffix + - entityType: Host + fieldMappings: + - identifier: HostName + columnName: ComputerName - entityType: IP fieldMappings: - identifier: Address columnName: CallerIpAddress -version: 2.0.1 +version: 2.0.2 kind: Scheduled \ No newline at end of file diff --git a/Solutions/Azure Activity/Analytic Rules/NRT_Creation_of_Expensive_Computes_in_Azure.yaml b/Solutions/Azure Activity/Analytic Rules/NRT_Creation_of_Expensive_Computes_in_Azure.yaml index 1d01c9e6a12..1305177c0e5 100644 --- a/Solutions/Azure Activity/Analytic Rules/NRT_Creation_of_Expensive_Computes_in_Azure.yaml +++ b/Solutions/Azure Activity/Analytic Rules/NRT_Creation_of_Expensive_Computes_in_Azure.yaml @@ -16,7 +16,7 @@ tactics: relevantTechniques: - T1578 query: | - let tokens = dynamic(["416","208","192","128","120","96","80","72","64","48","44","40","g5","gs5","g4","gs4","nc12","nc24","nv24"]); + let tokens = dynamic(["416","208","192","128","120","96","80","72","64","48","44","40","nc12","nc24","nv24"]); let operationList = dynamic(["microsoft.compute/virtualmachines/write", "microsoft.resources/deployments/write"]); AzureActivity | where OperationNameValue in~ (operationList) @@ -24,7 +24,7 @@ query: | | where Properties has 'vmSize' | extend parsed_property= parse_json(tostring((parse_json(Properties).responseBody))).properties | extend vmSize = tostring((parsed_property.hardwareProfile).vmSize) - | where vmSize has_any (tokens) + | mv-apply token=tokens to typeof(string) on (where vmSize contains token) | extend ComputerName = tostring((parsed_property.osProfile).computerName) | project TimeGenerated, OperationNameValue, ActivityStatusValue, Caller, CallerIpAddress, ComputerName, vmSize | extend Name = tostring(split(Caller,'@',0)[0]), UPNSuffix = tostring(split(Caller,'@',1)[0]) @@ -35,9 +35,13 @@ entityMappings: columnName: Name - identifier: UPNSuffix columnName: UPNSuffix + - entityType: Host + fieldMappings: + - identifier: HostName + columnName: ComputerName - entityType: IP fieldMappings: - identifier: Address columnName: CallerIpAddress -version: 2.0.1 +version: 2.0.2 kind: NRT diff --git a/Solutions/Azure Activity/Data Connectors/AzureActivity.JSON b/Solutions/Azure Activity/Data Connectors/AzureActivity.json similarity index 100% rename from Solutions/Azure Activity/Data Connectors/AzureActivity.JSON rename to Solutions/Azure Activity/Data Connectors/AzureActivity.json diff --git a/Solutions/Azure Activity/Data/Solution_AzureActivity.json b/Solutions/Azure Activity/Data/Solution_AzureActivity.json index 68d545bc035..82f2b2af2e9 100644 --- a/Solutions/Azure Activity/Data/Solution_AzureActivity.json +++ b/Solutions/Azure Activity/Data/Solution_AzureActivity.json @@ -40,7 +40,7 @@ "Workbooks/AzureActivity.json" ], "BasePath": "C:\\GitHub\\Azure-Sentinel\\solutions\\Azure Activity", - "Version": "2.0.6", + "Version": "3.0.0", "Metadata": "SolutionMetadata.json", "TemplateSpec": true, "Is1PConnector": true diff --git a/Solutions/Azure Activity/Data/system_generated_metadata.json b/Solutions/Azure Activity/Data/system_generated_metadata.json new file mode 100644 index 00000000000..1997cee0cd0 --- /dev/null +++ b/Solutions/Azure Activity/Data/system_generated_metadata.json @@ -0,0 +1,33 @@ +{ + "Name": "Azure Activity", + "Author": "Microsoft - support@microsoft.com", + "Logo": "", + "Description": "The [Azure Activity](https://docs.microsoft.com/azure/azure-monitor/essentials/activity-log) solution for Microsoft Sentinel enables you to ingest Azure Activity Administrative, Security, Service Health, Alert, Recommendation, Policy, Autoscale and Resource Health [logs](https://docs.microsoft.com/azure/azure-monitor/reference/tables/azureactivity) using Diagnostic Settings into Microsoft Sentinel.", + "BasePath": "C:\\GitHub\\Azure-Sentinel\\solutions\\Azure Activity", + "Version": "3.0.0", + "Metadata": "SolutionMetadata.json", + "TemplateSpec": true, + "Is1PConnector": true, + "publisherId": "azuresentinel", + "offerId": "azure-sentinel-solution-azureactivity", + "providers": [ + "Microsoft" + ], + "categories": { + "domains": [ + "IT Operations" + ], + "verticals": [] + }, + "firstPublishDate": "2022-04-18", + "support": { + "tier": "Microsoft", + "name": "Microsoft Corporation", + "email": "support@microsoft.com", + "link": "https://support.microsoft.com/" + }, + "Data Connectors": "[\n \"Data Connectors/AzureActivity.json\"\n]", + "Workbooks": "[\n \"Workbooks/AzureActivity.json\"\n]", + "Analytic Rules": "[\n \"AADHybridHealthADFSNewServer.yaml\",\n \"AADHybridHealthADFSServiceDelete.yaml\",\n \"AADHybridHealthADFSSuspApp.yaml\",\n \"Creating_Anomalous_Number_Of_Resources_detection.yaml\",\n \"Creation_of_Expensive_Computes_in_Azure.yaml\",\n \"Granting_Permissions_To_Account_detection.yaml\",\n \"NRT-AADHybridHealthADFSNewServer.yaml\",\n \"NRT_Creation_of_Expensive_Computes_in_Azure.yaml\",\n \"New-CloudShell-User.yaml\",\n \"NewResourceGroupsDeployedTo.yaml\",\n \"RareOperations.yaml\",\n \"TimeSeriesAnomaly_Mass_Cloud_Resource_Deletions.yaml\"\n]", + "Hunting Queries": "[\n \"AnalyticsRulesAdministrativeOperations.yaml\",\n \"AnomalousAzureOperationModel.yaml\",\n \"Anomalous_Listing_Of_Storage_Keys.yaml\",\n \"AzureAdministrationFromVPS.yaml\",\n \"AzureNSG_AdministrativeOperations.yaml\",\n \"AzureRunCommandFromAzureIP.yaml\",\n \"AzureSentinelConnectors_AdministrativeOperations.yaml\",\n \"AzureSentinelWorkbooks_AdministrativeOperation.yaml\",\n \"AzureVirtualNetworkSubnets_AdministrativeOperationset.yaml\",\n \"Common_Deployed_Resources.yaml\",\n \"Creating_Anomalous_Number_Of_Resources.yaml\",\n \"Granting_Permissions_to_Account.yaml\",\n \"PortOpenedForAzureResource.yaml\",\n \"Rare_Custom_Script_Extension.yaml\"\n]" +} diff --git a/Solutions/Azure Activity/Hunting Queries/AnomalousAzureOperationModel.yaml b/Solutions/Azure Activity/Hunting Queries/AnomalousAzureOperationModel.yaml index 797d69d1253..522f549e90c 100644 --- a/Solutions/Azure Activity/Hunting Queries/AnomalousAzureOperationModel.yaml +++ b/Solutions/Azure Activity/Hunting Queries/AnomalousAzureOperationModel.yaml @@ -1,6 +1,8 @@ id: 43cb0347-bdcc-4e83-af5a-cebbd03971d8 name: Anomalous Azure Operation Hunting Model description: | + 'This query identifies Azure Operation anomalies during threat hunts. It detects new callers, IPs, IP ranges, and anomalous operations. Initially set for Run Command operations, it can be configured for other operations and resource types.' +description_detailed: | 'This query can be used during threat hunts to identify a range of different Azure Operation anomalies. The query is heavily commented inline to explain operation. Anomalies covered are: New Caller, New Caller IP, New Caller IP Range, Anomalous operation based on Jaccard index. By default this query is configured to detect diff --git a/Solutions/Azure Activity/Hunting Queries/Anomalous_Listing_Of_Storage_Keys.yaml b/Solutions/Azure Activity/Hunting Queries/Anomalous_Listing_Of_Storage_Keys.yaml index 0292aaab633..e706ffc747c 100644 --- a/Solutions/Azure Activity/Hunting Queries/Anomalous_Listing_Of_Storage_Keys.yaml +++ b/Solutions/Azure Activity/Hunting Queries/Anomalous_Listing_Of_Storage_Keys.yaml @@ -1,6 +1,8 @@ id: 5d2399f9-ea5c-4e67-9435-1fba745f3a39 name: Azure storage key enumeration description: | + 'Azure's storage key listing can expose secrets, PII, and grant VM access. Monitoring for anomalous accounts or IPs is crucial. The query generates IP clusters, correlates activities, and flags unexpected ones. Single-operation users are excluded.' +description_detailed: | 'Listing of storage keys is an interesting operation in Azure which might expose additional secrets and PII to callers as well as granting access to VMs. While there are many benign operations of this type, it would be interesting to see if the account performing this activity or the source IP address from diff --git a/Solutions/Azure Activity/Hunting Queries/Common_Deployed_Resources.yaml b/Solutions/Azure Activity/Hunting Queries/Common_Deployed_Resources.yaml index 9f24f89635e..a80b53e3ae7 100644 --- a/Solutions/Azure Activity/Hunting Queries/Common_Deployed_Resources.yaml +++ b/Solutions/Azure Activity/Hunting Queries/Common_Deployed_Resources.yaml @@ -1,10 +1,12 @@ id: 0278e3b8-9899-45c5-8928-700cd80d2d80 name: Common deployed resources description: | + 'This query identifies common deployed resources in Azure, like resource names and groups. It can be used with other suspicious deployment signals to evaluate if a resource is commonly deployed or unique.' +description_detailed: | 'This query looks for common deployed resources (resource name and resource groups) and can be used in combination with other signals that show suspicious deployment to evaluate if the resource is one that is commonly being deployed/created or unique. - To understand the basket() function better see - https://docs.microsoft.com/azure/data-explorer/kusto/query/basketplugin' + To understand the basket() function better see - https://docs.microsoft.com/azure/data-explorer/kusto/query/basketplugin' requiredDataConnectors: - connectorId: AzureActivity dataTypes: diff --git a/Solutions/Azure Activity/Hunting Queries/PortOpenedForAzureResource.yaml b/Solutions/Azure Activity/Hunting Queries/PortOpenedForAzureResource.yaml index e2b0a0fd607..26a1fc68c2e 100644 --- a/Solutions/Azure Activity/Hunting Queries/PortOpenedForAzureResource.yaml +++ b/Solutions/Azure Activity/Hunting Queries/PortOpenedForAzureResource.yaml @@ -1,7 +1,7 @@ id: 9e146876-e303-49af-b847-b029d1a66852 name: Port opened for an Azure Resource description: | - 'Identifies what ports may have been opened for a given Azure Resource over the last 7 days' + 'Identifies what ports may have been opened for a given Azure Resource over the last 7 days.' requiredDataConnectors: - connectorId: AzureActivity dataTypes: diff --git a/Solutions/Azure Activity/Hunting Queries/Rare_Custom_Script_Extension.yaml b/Solutions/Azure Activity/Hunting Queries/Rare_Custom_Script_Extension.yaml index c6f6622cd5a..d28258581cb 100644 --- a/Solutions/Azure Activity/Hunting Queries/Rare_Custom_Script_Extension.yaml +++ b/Solutions/Azure Activity/Hunting Queries/Rare_Custom_Script_Extension.yaml @@ -1,7 +1,9 @@ id: 81fd68a2-9ad6-4a1c-7bd7-18efe5c99081 name: Rare Custom Script Extension description: | - 'The Custom Script Extension downloads and executes scripts on Azure virtual machines. This extension is useful for post deployment configuration, software installation, or any other configuration or management tasks. + 'The Custom Script Extension in Azure executes scripts on VMs, useful for post-deployment tasks. Scripts can be from various sources and could be used maliciously. The query identifies rare custom script extensions executed in your environment.' +description_detailed: | + 'The Custom Script Extension downloads and executes scripts on Azure virtual machines. This extension is useful for post deployment configuration, software installation, or any other configuration or management tasks. Scripts could be downloaded from external links, Azure storage, GitHub, or provided to the Azure portal at extension run time. This could also be used maliciously by an attacker. The query tries to identify rare custom script extensions that have been executed in your environment' requiredDataConnectors: diff --git a/Solutions/Azure Activity/Package/3.0.0.zip b/Solutions/Azure Activity/Package/3.0.0.zip new file mode 100644 index 00000000000..e0cd87c29a0 Binary files /dev/null and b/Solutions/Azure Activity/Package/3.0.0.zip differ diff --git a/Solutions/Azure Activity/Package/createUiDefinition.json b/Solutions/Azure Activity/Package/createUiDefinition.json index 46ff1ffacaa..2f093f2d208 100644 --- a/Solutions/Azure Activity/Package/createUiDefinition.json +++ b/Solutions/Azure Activity/Package/createUiDefinition.json @@ -88,7 +88,7 @@ "name": "workbooks-text", "type": "Microsoft.Common.TextBlock", "options": { - "text": "The workbooks installed with the Azure Activity solution provide insights into operations on different Azure resources. After installing the solution, start using the workbook in Manage solution view." + "text": "This solution installs workbook(s) to help you gain insights into the telemetry collected in Microsoft Sentinel. After installing the solution, start using the workbook in Manage solution view." } }, { @@ -358,7 +358,7 @@ "name": "huntingquery2-text", "type": "Microsoft.Common.TextBlock", "options": { - "text": "This query can be used during threat hunts to identify a range of different Azure Operation anomalies.\nThe query is heavily commented inline to explain operation. Anomalies covered are: New Caller, New Caller IP,\nNew Caller IP Range, Anomalous operation based on Jaccard index. By default this query is configured to detect\nanomalous Run Command operations. The operation and resource type to perform anomaly detection can be configured \nat the top of the query along with the detection window parameters This hunting query depends on AzureActivity data connector (AzureActivity Parser or Table)" + "text": "This query identifies Azure Operation anomalies during threat hunts. It detects new callers, IPs, IP ranges, and anomalous operations. Initially set for Run Command operations, it can be configured for other operations and resource types. This hunting query depends on AzureActivity data connector (AzureActivity Parser or Table)" } } ] @@ -372,7 +372,7 @@ "name": "huntingquery3-text", "type": "Microsoft.Common.TextBlock", "options": { - "text": "Listing of storage keys is an interesting operation in Azure which might expose additional \nsecrets and PII to callers as well as granting access to VMs. While there are many benign operations of this\ntype, it would be interesting to see if the account performing this activity or the source IP address from \nwhich it is being done is anomalous. \nThe query below generates known clusters of ip address per caller, notice that users which only had single\noperations do not appear in this list as we cannot learn from it their normal activity (only based on a single\nevent). The activities for listing storage account keys is correlated with this learned \nclusters of expected activities and activity which is not expected is returned. This hunting query depends on AzureActivity data connector (AzureActivity Parser or Table)" + "text": "Azure's storage key listing can expose secrets, PII, and grant VM access. Monitoring for anomalous accounts or IPs is crucial. The query generates IP clusters, correlates activities, and flags unexpected ones. Single-operation users are excluded. This hunting query depends on AzureActivity data connector (AzureActivity Parser or Table)" } } ] @@ -470,7 +470,7 @@ "name": "huntingquery10-text", "type": "Microsoft.Common.TextBlock", "options": { - "text": "This query looks for common deployed resources (resource name and resource groups) and can be used\nin combination with other signals that show suspicious deployment to evaluate if the resource is one\nthat is commonly being deployed/created or unique.\nTo understand the basket() function better see - https://docs.microsoft.com/azure/data-explorer/kusto/query/basketplugin This hunting query depends on AzureActivity data connector (AzureActivity Parser or Table)" + "text": "This query identifies common deployed resources in Azure, like resource names and groups. It can be used with other suspicious deployment signals to evaluate if a resource is commonly deployed or unique. This hunting query depends on AzureActivity data connector (AzureActivity Parser or Table)" } } ] @@ -512,7 +512,7 @@ "name": "huntingquery13-text", "type": "Microsoft.Common.TextBlock", "options": { - "text": "Identifies what ports may have been opened for a given Azure Resource over the last 7 days This hunting query depends on AzureActivity data connector (AzureActivity Parser or Table)" + "text": "Identifies what ports may have been opened for a given Azure Resource over the last 7 days. This hunting query depends on AzureActivity data connector (AzureActivity Parser or Table)" } } ] @@ -526,7 +526,7 @@ "name": "huntingquery14-text", "type": "Microsoft.Common.TextBlock", "options": { - "text": "The Custom Script Extension downloads and executes scripts on Azure virtual machines. This extension is useful for post deployment configuration, software installation, or any other configuration or management tasks.\n Scripts could be downloaded from external links, Azure storage, GitHub, or provided to the Azure portal at extension run time. This could also be used maliciously by an attacker.\n The query tries to identify rare custom script extensions that have been executed in your environment This hunting query depends on AzureActivity data connector (AzureActivity Parser or Table)" + "text": "The Custom Script Extension in Azure executes scripts on VMs, useful for post-deployment tasks. Scripts can be from various sources and could be used maliciously. The query identifies rare custom script extensions executed in your environment. This hunting query depends on AzureActivity data connector (AzureActivity Parser or Table)" } } ] diff --git a/Solutions/Azure Activity/Package/mainTemplate.json b/Solutions/Azure Activity/Package/mainTemplate.json index c84fb96717c..1d2f2091853 100644 --- a/Solutions/Azure Activity/Package/mainTemplate.json +++ b/Solutions/Azure Activity/Package/mainTemplate.json @@ -42,182 +42,193 @@ "_solutionId": "[variables('solutionId')]", "email": "support@microsoft.com", "_email": "[variables('email')]", - "workspaceResourceId": "[resourceId('microsoft.OperationalInsights/Workspaces', parameters('workspace'))]", + "_solutionName": "Azure Activity", + "_solutionVersion": "3.0.0", "uiConfigId1": "AzureActivity", "_uiConfigId1": "[variables('uiConfigId1')]", "dataConnectorContentId1": "AzureActivity", "_dataConnectorContentId1": "[variables('dataConnectorContentId1')]", "dataConnectorId1": "[extensionResourceId(resourceId('Microsoft.OperationalInsights/workspaces', parameters('workspace')), 'Microsoft.SecurityInsights/dataConnectors', variables('_dataConnectorContentId1'))]", "_dataConnectorId1": "[variables('dataConnectorId1')]", - "dataConnectorTemplateSpecName1": "[concat(parameters('workspace'),'-dc-',uniquestring(variables('_dataConnectorContentId1')))]", + "dataConnectorTemplateSpecName1": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/',concat(parameters('workspace'),'-dc-',uniquestring(variables('_dataConnectorContentId1'))))]", "dataConnectorVersion1": "2.0.0", + "_dataConnectorcontentProductId1": "[concat(take(variables('_solutionId'),50),'-','dc','-', uniqueString(concat(variables('_solutionId'),'-','DataConnector','-',variables('_dataConnectorContentId1'),'-', variables('dataConnectorVersion1'))))]", + "workbookVersion1": "2.0.0", + "workbookContentId1": "AzureActivityWorkbook", + "workbookId1": "[resourceId('Microsoft.Insights/workbooks', variables('workbookContentId1'))]", + "workbookTemplateSpecName1": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/',concat(parameters('workspace'),'-wb-',uniquestring(variables('_workbookContentId1'))))]", + "_workbookContentId1": "[variables('workbookContentId1')]", + "workspaceResourceId": "[resourceId('microsoft.OperationalInsights/Workspaces', parameters('workspace'))]", + "_workbookcontentProductId1": "[concat(take(variables('_solutionId'),50),'-','wb','-', uniqueString(concat(variables('_solutionId'),'-','Workbook','-',variables('_workbookContentId1'),'-', variables('workbookVersion1'))))]", + "analyticRuleVersion1": "2.0.1", + "analyticRulecontentId1": "88f453ff-7b9e-45bb-8c12-4058ca5e44ee", + "_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": "2.0.1", + "analyticRulecontentId2": "86a036b2-3686-42eb-b417-909fc0867771", + "_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": "2.0.1", + "analyticRulecontentId3": "d9938c3b-16f9-444d-bc22-ea9a9110e0fd", + "_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": "2.0.3", + "analyticRulecontentId4": "361dd1e3-1c11-491e-82a3-bb2e44ac36ba", + "_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": "2.0.2", + "analyticRulecontentId5": "9736e5f1-7b6e-4bfb-a708-e53ff1d182c3", + "_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": "2.0.1", + "analyticRulecontentId6": "b2c15736-b9eb-4dae-8b02-3016b6a45a32", + "_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": "2.0.1", + "analyticRulecontentId7": "ec491363-5fe7-4eff-b68e-f42dcb76fcf6", + "_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": "2.0.2", + "analyticRulecontentId8": "56fe0db0-6779-46fa-b3c5-006082a53064", + "_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": "2.0.2", + "analyticRulecontentId9": "6d7214d9-4a28-44df-aafb-0910b9e6ae3e", + "_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": "2.0.2", + "analyticRulecontentId10": "9fb57e58-3ed8-4b89-afcf-c8e786508b1c", + "_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": "2.0.2", + "analyticRulecontentId11": "23de46ea-c425-4a77-b456-511ae4855d69", + "_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": "2.0.2", + "analyticRulecontentId12": "ed43bdb7-eaab-4ea4-be52-6951fcfa7e3b", + "_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'))))]", "huntingQueryVersion1": "2.0.1", "huntingQuerycontentId1": "ef7ef44e-6129-4d8e-94fe-b5530415d8e5", "_huntingQuerycontentId1": "[variables('huntingQuerycontentId1')]", "huntingQueryId1": "[resourceId('Microsoft.OperationalInsights/savedSearches', variables('_huntingQuerycontentId1'))]", - "huntingQueryTemplateSpecName1": "[concat(parameters('workspace'),'-hq-',uniquestring(variables('_huntingQuerycontentId1')))]", + "huntingQueryTemplateSpecName1": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/',concat(parameters('workspace'),'-hq-',uniquestring(variables('_huntingQuerycontentId1'))))]", + "_huntingQuerycontentProductId1": "[concat(take(variables('_solutionId'),50),'-','hq','-', uniqueString(concat(variables('_solutionId'),'-','HuntingQuery','-',variables('_huntingQuerycontentId1'),'-', variables('huntingQueryVersion1'))))]", "huntingQueryVersion2": "2.0.0", "huntingQuerycontentId2": "43cb0347-bdcc-4e83-af5a-cebbd03971d8", "_huntingQuerycontentId2": "[variables('huntingQuerycontentId2')]", "huntingQueryId2": "[resourceId('Microsoft.OperationalInsights/savedSearches', variables('_huntingQuerycontentId2'))]", - "huntingQueryTemplateSpecName2": "[concat(parameters('workspace'),'-hq-',uniquestring(variables('_huntingQuerycontentId2')))]", + "huntingQueryTemplateSpecName2": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/',concat(parameters('workspace'),'-hq-',uniquestring(variables('_huntingQuerycontentId2'))))]", + "_huntingQuerycontentProductId2": "[concat(take(variables('_solutionId'),50),'-','hq','-', uniqueString(concat(variables('_solutionId'),'-','HuntingQuery','-',variables('_huntingQuerycontentId2'),'-', variables('huntingQueryVersion2'))))]", "huntingQueryVersion3": "2.0.1", "huntingQuerycontentId3": "5d2399f9-ea5c-4e67-9435-1fba745f3a39", "_huntingQuerycontentId3": "[variables('huntingQuerycontentId3')]", "huntingQueryId3": "[resourceId('Microsoft.OperationalInsights/savedSearches', variables('_huntingQuerycontentId3'))]", - "huntingQueryTemplateSpecName3": "[concat(parameters('workspace'),'-hq-',uniquestring(variables('_huntingQuerycontentId3')))]", + "huntingQueryTemplateSpecName3": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/',concat(parameters('workspace'),'-hq-',uniquestring(variables('_huntingQuerycontentId3'))))]", + "_huntingQuerycontentProductId3": "[concat(take(variables('_solutionId'),50),'-','hq','-', uniqueString(concat(variables('_solutionId'),'-','HuntingQuery','-',variables('_huntingQuerycontentId3'),'-', variables('huntingQueryVersion3'))))]", "huntingQueryVersion4": "2.0.1", "huntingQuerycontentId4": "1b8779c9-abf2-444f-a21f-437b8f90ac4a", "_huntingQuerycontentId4": "[variables('huntingQuerycontentId4')]", "huntingQueryId4": "[resourceId('Microsoft.OperationalInsights/savedSearches', variables('_huntingQuerycontentId4'))]", - "huntingQueryTemplateSpecName4": "[concat(parameters('workspace'),'-hq-',uniquestring(variables('_huntingQuerycontentId4')))]", + "huntingQueryTemplateSpecName4": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/',concat(parameters('workspace'),'-hq-',uniquestring(variables('_huntingQuerycontentId4'))))]", + "_huntingQuerycontentProductId4": "[concat(take(variables('_solutionId'),50),'-','hq','-', uniqueString(concat(variables('_solutionId'),'-','HuntingQuery','-',variables('_huntingQuerycontentId4'),'-', variables('huntingQueryVersion4'))))]", "huntingQueryVersion5": "2.0.1", "huntingQuerycontentId5": "e94d6756-981c-4f02-9a81-d006d80c8b41", "_huntingQuerycontentId5": "[variables('huntingQuerycontentId5')]", "huntingQueryId5": "[resourceId('Microsoft.OperationalInsights/savedSearches', variables('_huntingQuerycontentId5'))]", - "huntingQueryTemplateSpecName5": "[concat(parameters('workspace'),'-hq-',uniquestring(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'))))]", "huntingQueryVersion6": "2.1.1", "huntingQuerycontentId6": "efe843ca-3ce7-4896-9f8b-f2c374ae6527", "_huntingQuerycontentId6": "[variables('huntingQuerycontentId6')]", "huntingQueryId6": "[resourceId('Microsoft.OperationalInsights/savedSearches', variables('_huntingQuerycontentId6'))]", - "huntingQueryTemplateSpecName6": "[concat(parameters('workspace'),'-hq-',uniquestring(variables('_huntingQuerycontentId6')))]", + "huntingQueryTemplateSpecName6": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/',concat(parameters('workspace'),'-hq-',uniquestring(variables('_huntingQuerycontentId6'))))]", + "_huntingQuerycontentProductId6": "[concat(take(variables('_solutionId'),50),'-','hq','-', uniqueString(concat(variables('_solutionId'),'-','HuntingQuery','-',variables('_huntingQuerycontentId6'),'-', variables('huntingQueryVersion6'))))]", "huntingQueryVersion7": "2.0.1", "huntingQuerycontentId7": "17201aa8-0916-4078-a020-7ea3a9262889", "_huntingQuerycontentId7": "[variables('huntingQuerycontentId7')]", "huntingQueryId7": "[resourceId('Microsoft.OperationalInsights/savedSearches', variables('_huntingQuerycontentId7'))]", - "huntingQueryTemplateSpecName7": "[concat(parameters('workspace'),'-hq-',uniquestring(variables('_huntingQuerycontentId7')))]", + "huntingQueryTemplateSpecName7": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/',concat(parameters('workspace'),'-hq-',uniquestring(variables('_huntingQuerycontentId7'))))]", + "_huntingQuerycontentProductId7": "[concat(take(variables('_solutionId'),50),'-','hq','-', uniqueString(concat(variables('_solutionId'),'-','HuntingQuery','-',variables('_huntingQuerycontentId7'),'-', variables('huntingQueryVersion7'))))]", "huntingQueryVersion8": "2.0.1", "huntingQuerycontentId8": "5a1f9655-c893-4091-8dc0-7f11d7676506", "_huntingQuerycontentId8": "[variables('huntingQuerycontentId8')]", "huntingQueryId8": "[resourceId('Microsoft.OperationalInsights/savedSearches', variables('_huntingQuerycontentId8'))]", - "huntingQueryTemplateSpecName8": "[concat(parameters('workspace'),'-hq-',uniquestring(variables('_huntingQuerycontentId8')))]", + "huntingQueryTemplateSpecName8": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/',concat(parameters('workspace'),'-hq-',uniquestring(variables('_huntingQuerycontentId8'))))]", + "_huntingQuerycontentProductId8": "[concat(take(variables('_solutionId'),50),'-','hq','-', uniqueString(concat(variables('_solutionId'),'-','HuntingQuery','-',variables('_huntingQuerycontentId8'),'-', variables('huntingQueryVersion8'))))]", "huntingQueryVersion9": "2.0.1", "huntingQuerycontentId9": "57784ba5-7791-422e-916f-65ef94fe1dbb", "_huntingQuerycontentId9": "[variables('huntingQuerycontentId9')]", "huntingQueryId9": "[resourceId('Microsoft.OperationalInsights/savedSearches', variables('_huntingQuerycontentId9'))]", - "huntingQueryTemplateSpecName9": "[concat(parameters('workspace'),'-hq-',uniquestring(variables('_huntingQuerycontentId9')))]", + "huntingQueryTemplateSpecName9": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/',concat(parameters('workspace'),'-hq-',uniquestring(variables('_huntingQuerycontentId9'))))]", + "_huntingQuerycontentProductId9": "[concat(take(variables('_solutionId'),50),'-','hq','-', uniqueString(concat(variables('_solutionId'),'-','HuntingQuery','-',variables('_huntingQuerycontentId9'),'-', variables('huntingQueryVersion9'))))]", "huntingQueryVersion10": "2.0.1", "huntingQuerycontentId10": "0278e3b8-9899-45c5-8928-700cd80d2d80", "_huntingQuerycontentId10": "[variables('huntingQuerycontentId10')]", "huntingQueryId10": "[resourceId('Microsoft.OperationalInsights/savedSearches', variables('_huntingQuerycontentId10'))]", - "huntingQueryTemplateSpecName10": "[concat(parameters('workspace'),'-hq-',uniquestring(variables('_huntingQuerycontentId10')))]", + "huntingQueryTemplateSpecName10": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/',concat(parameters('workspace'),'-hq-',uniquestring(variables('_huntingQuerycontentId10'))))]", + "_huntingQuerycontentProductId10": "[concat(take(variables('_solutionId'),50),'-','hq','-', uniqueString(concat(variables('_solutionId'),'-','HuntingQuery','-',variables('_huntingQuerycontentId10'),'-', variables('huntingQueryVersion10'))))]", "huntingQueryVersion11": "2.0.1", "huntingQuerycontentId11": "a09e6368-065b-4f1e-a4ce-b1b3a64b493b", "_huntingQuerycontentId11": "[variables('huntingQuerycontentId11')]", "huntingQueryId11": "[resourceId('Microsoft.OperationalInsights/savedSearches', variables('_huntingQuerycontentId11'))]", - "huntingQueryTemplateSpecName11": "[concat(parameters('workspace'),'-hq-',uniquestring(variables('_huntingQuerycontentId11')))]", + "huntingQueryTemplateSpecName11": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/',concat(parameters('workspace'),'-hq-',uniquestring(variables('_huntingQuerycontentId11'))))]", + "_huntingQuerycontentProductId11": "[concat(take(variables('_solutionId'),50),'-','hq','-', uniqueString(concat(variables('_solutionId'),'-','HuntingQuery','-',variables('_huntingQuerycontentId11'),'-', variables('huntingQueryVersion11'))))]", "huntingQueryVersion12": "2.0.1", "huntingQuerycontentId12": "860cda84-765b-4273-af44-958b7cca85f7", "_huntingQuerycontentId12": "[variables('huntingQuerycontentId12')]", "huntingQueryId12": "[resourceId('Microsoft.OperationalInsights/savedSearches', variables('_huntingQuerycontentId12'))]", - "huntingQueryTemplateSpecName12": "[concat(parameters('workspace'),'-hq-',uniquestring(variables('_huntingQuerycontentId12')))]", + "huntingQueryTemplateSpecName12": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/',concat(parameters('workspace'),'-hq-',uniquestring(variables('_huntingQuerycontentId12'))))]", + "_huntingQuerycontentProductId12": "[concat(take(variables('_solutionId'),50),'-','hq','-', uniqueString(concat(variables('_solutionId'),'-','HuntingQuery','-',variables('_huntingQuerycontentId12'),'-', variables('huntingQueryVersion12'))))]", "huntingQueryVersion13": "2.0.1", "huntingQuerycontentId13": "9e146876-e303-49af-b847-b029d1a66852", "_huntingQuerycontentId13": "[variables('huntingQuerycontentId13')]", "huntingQueryId13": "[resourceId('Microsoft.OperationalInsights/savedSearches', variables('_huntingQuerycontentId13'))]", - "huntingQueryTemplateSpecName13": "[concat(parameters('workspace'),'-hq-',uniquestring(variables('_huntingQuerycontentId13')))]", + "huntingQueryTemplateSpecName13": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/',concat(parameters('workspace'),'-hq-',uniquestring(variables('_huntingQuerycontentId13'))))]", + "_huntingQuerycontentProductId13": "[concat(take(variables('_solutionId'),50),'-','hq','-', uniqueString(concat(variables('_solutionId'),'-','HuntingQuery','-',variables('_huntingQuerycontentId13'),'-', variables('huntingQueryVersion13'))))]", "huntingQueryVersion14": "2.0.1", "huntingQuerycontentId14": "81fd68a2-9ad6-4a1c-7bd7-18efe5c99081", "_huntingQuerycontentId14": "[variables('huntingQuerycontentId14')]", "huntingQueryId14": "[resourceId('Microsoft.OperationalInsights/savedSearches', variables('_huntingQuerycontentId14'))]", - "huntingQueryTemplateSpecName14": "[concat(parameters('workspace'),'-hq-',uniquestring(variables('_huntingQuerycontentId14')))]", - "analyticRuleVersion1": "2.0.1", - "analyticRulecontentId1": "88f453ff-7b9e-45bb-8c12-4058ca5e44ee", - "_analyticRulecontentId1": "[variables('analyticRulecontentId1')]", - "analyticRuleId1": "[resourceId('Microsoft.SecurityInsights/AlertRuleTemplates', variables('analyticRulecontentId1'))]", - "analyticRuleTemplateSpecName1": "[concat(parameters('workspace'),'-ar-',uniquestring(variables('_analyticRulecontentId1')))]", - "analyticRuleVersion2": "2.0.1", - "analyticRulecontentId2": "86a036b2-3686-42eb-b417-909fc0867771", - "_analyticRulecontentId2": "[variables('analyticRulecontentId2')]", - "analyticRuleId2": "[resourceId('Microsoft.SecurityInsights/AlertRuleTemplates', variables('analyticRulecontentId2'))]", - "analyticRuleTemplateSpecName2": "[concat(parameters('workspace'),'-ar-',uniquestring(variables('_analyticRulecontentId2')))]", - "analyticRuleVersion3": "2.0.1", - "analyticRulecontentId3": "d9938c3b-16f9-444d-bc22-ea9a9110e0fd", - "_analyticRulecontentId3": "[variables('analyticRulecontentId3')]", - "analyticRuleId3": "[resourceId('Microsoft.SecurityInsights/AlertRuleTemplates', variables('analyticRulecontentId3'))]", - "analyticRuleTemplateSpecName3": "[concat(parameters('workspace'),'-ar-',uniquestring(variables('_analyticRulecontentId3')))]", - "analyticRuleVersion4": "2.0.3", - "analyticRulecontentId4": "361dd1e3-1c11-491e-82a3-bb2e44ac36ba", - "_analyticRulecontentId4": "[variables('analyticRulecontentId4')]", - "analyticRuleId4": "[resourceId('Microsoft.SecurityInsights/AlertRuleTemplates', variables('analyticRulecontentId4'))]", - "analyticRuleTemplateSpecName4": "[concat(parameters('workspace'),'-ar-',uniquestring(variables('_analyticRulecontentId4')))]", - "analyticRuleVersion5": "2.0.1", - "analyticRulecontentId5": "9736e5f1-7b6e-4bfb-a708-e53ff1d182c3", - "_analyticRulecontentId5": "[variables('analyticRulecontentId5')]", - "analyticRuleId5": "[resourceId('Microsoft.SecurityInsights/AlertRuleTemplates', variables('analyticRulecontentId5'))]", - "analyticRuleTemplateSpecName5": "[concat(parameters('workspace'),'-ar-',uniquestring(variables('_analyticRulecontentId5')))]", - "analyticRuleVersion6": "2.0.1", - "analyticRulecontentId6": "b2c15736-b9eb-4dae-8b02-3016b6a45a32", - "_analyticRulecontentId6": "[variables('analyticRulecontentId6')]", - "analyticRuleId6": "[resourceId('Microsoft.SecurityInsights/AlertRuleTemplates', variables('analyticRulecontentId6'))]", - "analyticRuleTemplateSpecName6": "[concat(parameters('workspace'),'-ar-',uniquestring(variables('_analyticRulecontentId6')))]", - "analyticRuleVersion7": "2.0.1", - "analyticRulecontentId7": "ec491363-5fe7-4eff-b68e-f42dcb76fcf6", - "_analyticRulecontentId7": "[variables('analyticRulecontentId7')]", - "analyticRuleId7": "[resourceId('Microsoft.SecurityInsights/AlertRuleTemplates', variables('analyticRulecontentId7'))]", - "analyticRuleTemplateSpecName7": "[concat(parameters('workspace'),'-ar-',uniquestring(variables('_analyticRulecontentId7')))]", - "analyticRuleVersion8": "2.0.1", - "analyticRulecontentId8": "56fe0db0-6779-46fa-b3c5-006082a53064", - "_analyticRulecontentId8": "[variables('analyticRulecontentId8')]", - "analyticRuleId8": "[resourceId('Microsoft.SecurityInsights/AlertRuleTemplates', variables('analyticRulecontentId8'))]", - "analyticRuleTemplateSpecName8": "[concat(parameters('workspace'),'-ar-',uniquestring(variables('_analyticRulecontentId8')))]", - "analyticRuleVersion9": "2.0.2", - "analyticRulecontentId9": "6d7214d9-4a28-44df-aafb-0910b9e6ae3e", - "_analyticRulecontentId9": "[variables('analyticRulecontentId9')]", - "analyticRuleId9": "[resourceId('Microsoft.SecurityInsights/AlertRuleTemplates', variables('analyticRulecontentId9'))]", - "analyticRuleTemplateSpecName9": "[concat(parameters('workspace'),'-ar-',uniquestring(variables('_analyticRulecontentId9')))]", - "analyticRuleVersion10": "2.0.2", - "analyticRulecontentId10": "9fb57e58-3ed8-4b89-afcf-c8e786508b1c", - "_analyticRulecontentId10": "[variables('analyticRulecontentId10')]", - "analyticRuleId10": "[resourceId('Microsoft.SecurityInsights/AlertRuleTemplates', variables('analyticRulecontentId10'))]", - "analyticRuleTemplateSpecName10": "[concat(parameters('workspace'),'-ar-',uniquestring(variables('_analyticRulecontentId10')))]", - "analyticRuleVersion11": "2.0.2", - "analyticRulecontentId11": "23de46ea-c425-4a77-b456-511ae4855d69", - "_analyticRulecontentId11": "[variables('analyticRulecontentId11')]", - "analyticRuleId11": "[resourceId('Microsoft.SecurityInsights/AlertRuleTemplates', variables('analyticRulecontentId11'))]", - "analyticRuleTemplateSpecName11": "[concat(parameters('workspace'),'-ar-',uniquestring(variables('_analyticRulecontentId11')))]", - "analyticRuleVersion12": "2.0.2", - "analyticRulecontentId12": "ed43bdb7-eaab-4ea4-be52-6951fcfa7e3b", - "_analyticRulecontentId12": "[variables('analyticRulecontentId12')]", - "analyticRuleId12": "[resourceId('Microsoft.SecurityInsights/AlertRuleTemplates', variables('analyticRulecontentId12'))]", - "analyticRuleTemplateSpecName12": "[concat(parameters('workspace'),'-ar-',uniquestring(variables('_analyticRulecontentId12')))]", - "TemplateEmptyArray": "[json('[]')]", - "blanks": "[replace('b', 'b', '')]", - "workbookVersion1": "2.0.0", - "workbookContentId1": "AzureActivityWorkbook", - "workbookId1": "[resourceId('Microsoft.Insights/workbooks', variables('workbookContentId1'))]", - "workbookTemplateSpecName1": "[concat(parameters('workspace'),'-wb-',uniquestring(variables('_workbookContentId1')))]", - "_workbookContentId1": "[variables('workbookContentId1')]" + "huntingQueryTemplateSpecName14": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/',concat(parameters('workspace'),'-hq-',uniquestring(variables('_huntingQuerycontentId14'))))]", + "_huntingQuerycontentProductId14": "[concat(take(variables('_solutionId'),50),'-','hq','-', uniqueString(concat(variables('_solutionId'),'-','HuntingQuery','-',variables('_huntingQuerycontentId14'),'-', variables('huntingQueryVersion14'))))]", + "_solutioncontentProductId": "[concat(take(variables('_solutionId'),50),'-','sl','-', uniqueString(concat(variables('_solutionId'),'-','Solution','-',variables('_solutionId'),'-', variables('_solutionVersion'))))]" }, "resources": [ { - "type": "Microsoft.Resources/templateSpecs", - "apiVersion": "2022-02-01", + "type": "Microsoft.OperationalInsights/workspaces/providers/contentTemplates", + "apiVersion": "2023-04-01-preview", "name": "[variables('dataConnectorTemplateSpecName1')]", "location": "[parameters('workspace-location')]", - "tags": { - "hidden-sentinelWorkspaceId": "[variables('workspaceResourceId')]", - "hidden-sentinelContentType": "DataConnector" - }, - "properties": { - "description": "Azure Activity data connector with template", - "displayName": "Azure Activity template" - } - }, - { - "type": "Microsoft.Resources/templateSpecs/versions", - "apiVersion": "2022-02-01", - "name": "[concat(variables('dataConnectorTemplateSpecName1'),'/',variables('dataConnectorVersion1'))]", - "location": "[parameters('workspace-location')]", - "tags": { - "hidden-sentinelWorkspaceId": "[variables('workspaceResourceId')]", - "hidden-sentinelContentType": "DataConnector" - }, "dependsOn": [ - "[resourceId('Microsoft.Resources/templateSpecs', variables('dataConnectorTemplateSpecName1'))]" + "[extensionResourceId(resourceId('Microsoft.OperationalInsights/workspaces', parameters('workspace')), 'Microsoft.SecurityInsights/contentPackages', variables('_solutionId'))]" ], "properties": { - "description": "Azure Activity data connector with template version 2.0.6", + "description": "Azure Activity data connector with template version 3.0.0", "mainTemplate": { "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", "contentVersion": "[variables('dataConnectorVersion1')]", @@ -262,7 +273,7 @@ }, { "type": "Microsoft.OperationalInsights/workspaces/providers/metadata", - "apiVersion": "2022-01-01-preview", + "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'))]", @@ -287,12 +298,23 @@ } } ] - } + }, + "packageKind": "Solution", + "packageVersion": "[variables('_solutionVersion')]", + "packageName": "[variables('_solutionName')]", + "packageId": "[variables('_solutionId')]", + "contentSchemaVersion": "3.0.0", + "contentId": "[variables('_dataConnectorContentId1')]", + "contentKind": "DataConnector", + "displayName": "Azure Activity", + "contentProductId": "[variables('_dataConnectorcontentProductId1')]", + "id": "[variables('_dataConnectorcontentProductId1')]", + "version": "[variables('dataConnectorVersion1')]" } }, { "type": "Microsoft.OperationalInsights/workspaces/providers/metadata", - "apiVersion": "2022-01-01-preview", + "apiVersion": "2023-04-01-preview", "name": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/',concat('DataConnector-', last(split(variables('_dataConnectorId1'),'/'))))]", "dependsOn": [ "[variables('_dataConnectorId1')]" @@ -357,76 +379,48 @@ } }, { - "type": "Microsoft.Resources/templateSpecs", - "apiVersion": "2022-02-01", - "name": "[variables('huntingQueryTemplateSpecName1')]", - "location": "[parameters('workspace-location')]", - "tags": { - "hidden-sentinelWorkspaceId": "[variables('workspaceResourceId')]", - "hidden-sentinelContentType": "HuntingQuery" - }, - "properties": { - "description": "Azure Activity Hunting Query 1 with template", - "displayName": "Azure Activity Hunting Query template" - } - }, - { - "type": "Microsoft.Resources/templateSpecs/versions", - "apiVersion": "2022-02-01", - "name": "[concat(variables('huntingQueryTemplateSpecName1'),'/',variables('huntingQueryVersion1'))]", + "type": "Microsoft.OperationalInsights/workspaces/providers/contentTemplates", + "apiVersion": "2023-04-01-preview", + "name": "[variables('workbookTemplateSpecName1')]", "location": "[parameters('workspace-location')]", - "tags": { - "hidden-sentinelWorkspaceId": "[variables('workspaceResourceId')]", - "hidden-sentinelContentType": "HuntingQuery" - }, "dependsOn": [ - "[resourceId('Microsoft.Resources/templateSpecs', variables('huntingQueryTemplateSpecName1'))]" + "[extensionResourceId(resourceId('Microsoft.OperationalInsights/workspaces', parameters('workspace')), 'Microsoft.SecurityInsights/contentPackages', variables('_solutionId'))]" ], "properties": { - "description": "AnalyticsRulesAdministrativeOperations_HuntingQueries Hunting Query with template version 2.0.6", + "description": "AzureActivityWorkbook Workbook with template version 3.0.0", "mainTemplate": { "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", - "contentVersion": "[variables('huntingQueryVersion1')]", + "contentVersion": "[variables('workbookVersion1')]", "parameters": {}, "variables": {}, "resources": [ { - "type": "Microsoft.OperationalInsights/savedSearches", - "apiVersion": "2020-08-01", - "name": "Azure_Activity_Hunting_Query_1", + "type": "Microsoft.Insights/workbooks", + "name": "[variables('workbookContentId1')]", "location": "[parameters('workspace-location')]", + "kind": "shared", + "apiVersion": "2021-08-01", + "metadata": { + "description": "Gain extensive insight into your organization's Azure Activity by analyzing, and correlating all user operations and events.\nYou can learn about all user operations, trends, and anomalous changes over time.\nThis workbook gives you the ability to drill down into caller activities and summarize detected failure and warning events." + }, "properties": { - "eTag": "*", - "displayName": "Microsoft Sentinel Analytics Rules Administrative Operations", - "category": "Hunting Queries", - "query": "let opValues = dynamic([\"Microsoft.SecurityInsights/alertRules/write\", \"Microsoft.SecurityInsights/alertRules/delete\"]);\n// Microsoft Sentinel Analytics - Rule Create / Update / Delete\nAzureActivity\n| where Category =~ \"Administrative\"\n| where OperationNameValue in~ (opValues)\n| where ActivitySubstatusValue in~ (\"Created\", \"OK\")\n| sort by TimeGenerated desc\n| extend Name = tostring(split(Caller,'@',0)[0]), UPNSuffix = tostring(split(Caller,'@',1)[0])\n| extend Account_0_Name = Name\n| extend Account_0_UPNSuffix = UPNSuffix\n| extend IP_0_Address = CallerIpAddress\n", - "version": 2, - "tags": [ - { - "name": "description", - "value": "Identifies Microsoft Sentinel Analytics Rules administrative operations" - }, - { - "name": "tactics", - "value": "Impact" - }, - { - "name": "techniques", - "value": "T1496" - } - ] + "displayName": "[parameters('workbook1-name')]", + "serializedData": "{\"version\":\"Notebook/1.0\",\"items\":[{\"type\":9,\"content\":{\"version\":\"KqlParameterItem/1.0\",\"query\":\"\",\"parameters\":[{\"id\":\"52bfbd84-1639-480c-bda5-bfc87fd81832\",\"version\":\"KqlParameterItem/1.0\",\"name\":\"TimeRange\",\"type\":4,\"isRequired\":true,\"value\":{\"durationMs\":604800000},\"typeSettings\":{\"selectableValues\":[{\"durationMs\":300000},{\"durationMs\":900000},{\"durationMs\":1800000},{\"durationMs\":3600000},{\"durationMs\":14400000},{\"durationMs\":43200000},{\"durationMs\":86400000},{\"durationMs\":172800000},{\"durationMs\":259200000},{\"durationMs\":604800000},{\"durationMs\":1209600000},{\"durationMs\":2419200000},{\"durationMs\":2592000000},{\"durationMs\":5184000000},{\"durationMs\":7776000000}]}},{\"id\":\"eeb5dcf9-e898-46af-9c12-d91d97e13cd3\",\"version\":\"KqlParameterItem/1.0\",\"name\":\"Caller\",\"type\":2,\"isRequired\":true,\"multiSelect\":true,\"quote\":\"'\",\"delimiter\":\",\",\"query\":\"AzureActivity\\r\\n| summarize by Caller\",\"value\":[\"value::all\"],\"typeSettings\":{\"additionalResourceOptions\":[\"value::all\"],\"selectAllValue\":\"All\"},\"timeContext\":{\"durationMs\":0},\"timeContextFromParameter\":\"TimeRange\",\"queryType\":0,\"resourceType\":\"microsoft.operationalinsights/workspaces\"},{\"id\":\"46375a76-7ae1-4d7e-9082-4191531198a9\",\"version\":\"KqlParameterItem/1.0\",\"name\":\"ResourceGroup\",\"type\":2,\"isRequired\":true,\"multiSelect\":true,\"quote\":\"'\",\"delimiter\":\",\",\"query\":\"AzureActivity\\r\\n| summarize by ResourceGroup\",\"value\":[\"value::all\"],\"typeSettings\":{\"resourceTypeFilter\":{\"microsoft.resources/resourcegroups\":true},\"additionalResourceOptions\":[\"value::all\"],\"selectAllValue\":\"All\"},\"timeContext\":{\"durationMs\":0},\"timeContextFromParameter\":\"TimeRange\",\"queryType\":0,\"resourceType\":\"microsoft.operationalinsights/workspaces\"}],\"style\":\"pills\",\"queryType\":0,\"resourceType\":\"microsoft.operationalinsights/workspaces\"},\"name\":\"parameters - 2\"},{\"type\":3,\"content\":{\"version\":\"KqlItem/1.0\",\"query\":\"let data = AzureActivity\\r\\n| where \\\"{Caller:lable}\\\" == \\\"All\\\" or \\\"{Caller:lable}\\\" == \\\"All\\\" or Caller in ({Caller})\\r\\n| where \\\"{ResourceGroup:lable}\\\" == \\\"All\\\" or \\\"{ResourceGroup:lable}\\\" == \\\"All\\\" or ResourceGroup in ({ResourceGroup});\\r\\ndata\\r\\n| summarize Count = count() by ResourceGroup\\r\\n| join kind = fullouter (datatable(ResourceGroup:string)['Medium', 'high', 'low']) on ResourceGroup\\r\\n| project ResourceGroup = iff(ResourceGroup == '', ResourceGroup1, ResourceGroup), Count = iff(ResourceGroup == '', 0, Count)\\r\\n| join kind = inner (data\\r\\n | make-series Trend = count() default = 0 on TimeGenerated from {TimeRange:start} to {TimeRange:end} step {TimeRange:grain} by ResourceGroup)\\r\\n on ResourceGroup\\r\\n| project-away ResourceGroup1, TimeGenerated\\r\\n| extend ResourceGroups = ResourceGroup\\r\\n| union (\\r\\n data \\r\\n | summarize Count = count() \\r\\n | extend jkey = 1\\r\\n | join kind=inner (data\\r\\n | make-series Trend = count() default = 0 on TimeGenerated from {TimeRange:start} to {TimeRange:end} step {TimeRange:grain}\\r\\n | extend jkey = 1) on jkey\\r\\n | extend ResourceGroup = 'All', ResourceGroups = '*' \\r\\n)\\r\\n| order by Count desc\\r\\n| take 10\",\"size\":4,\"exportToExcelOptions\":\"visible\",\"title\":\"Top 10 active resource groups\",\"timeContext\":{\"durationMs\":0},\"timeContextFromParameter\":\"TimeRange\",\"queryType\":0,\"resourceType\":\"microsoft.operationalinsights/workspaces\",\"visualization\":\"tiles\",\"tileSettings\":{\"titleContent\":{\"columnMatch\":\"ResourceGroup\",\"formatter\":1,\"formatOptions\":{\"showIcon\":true}},\"leftContent\":{\"columnMatch\":\"Count\",\"formatter\":12,\"formatOptions\":{\"palette\":\"auto\",\"showIcon\":true},\"numberFormat\":{\"unit\":17,\"options\":{\"maximumSignificantDigits\":3,\"maximumFractionDigits\":2}}},\"secondaryContent\":{\"columnMatch\":\"Trend\",\"formatter\":9,\"formatOptions\":{\"palette\":\"blueOrange\",\"showIcon\":true}},\"showBorder\":false}},\"name\":\"query - 3\"},{\"type\":3,\"content\":{\"version\":\"KqlItem/1.0\",\"query\":\"AzureActivity\\r\\n| where \\\"{Caller:lable}\\\" == \\\"All\\\" or Caller in ({Caller})\\r\\n| where \\\"{ResourceGroup:lable}\\\" == \\\"All\\\" or ResourceGroup in ({ResourceGroup})\\r\\n| summarize deletions = countif(OperationNameValue hassuffix \\\"delete\\\"), creations = countif(OperationNameValue hassuffix \\\"write\\\"), updates = countif(OperationNameValue hassuffix \\\"write\\\"), Activities = count(OperationNameValue) by bin_at(TimeGenerated, 1h, now())\\r\\n\",\"size\":0,\"exportToExcelOptions\":\"visible\",\"title\":\"Activities over time\",\"color\":\"gray\",\"timeContext\":{\"durationMs\":0},\"timeContextFromParameter\":\"TimeRange\",\"queryType\":0,\"resourceType\":\"microsoft.operationalinsights/workspaces\",\"visualization\":\"linechart\",\"graphSettings\":{\"type\":0}},\"name\":\"query - 1\"},{\"type\":3,\"content\":{\"version\":\"KqlItem/1.0\",\"query\":\"AzureActivity\\r\\n| where \\\"{Caller:lable}\\\" == \\\"All\\\" or Caller in ({Caller})\\r\\n| where \\\"{ResourceGroup:lable}\\\" == \\\"All\\\" or ResourceGroup in ({ResourceGroup})\\r\\n| summarize deletions = countif(OperationNameValue hassuffix \\\"Delete\\\"), creations = countif(OperationNameValue hassuffix \\\"write\\\"), updates = countif(OperationNameValue hassuffix \\\"write\\\"), Activities = count() by Caller\\r\\n\",\"size\":1,\"exportToExcelOptions\":\"visible\",\"title\":\"Caller activities\",\"timeContext\":{\"durationMs\":0},\"timeContextFromParameter\":\"TimeRange\",\"queryType\":0,\"resourceType\":\"microsoft.operationalinsights/workspaces\",\"gridSettings\":{\"formatters\":[{\"columnMatch\":\"Caller\",\"formatter\":0,\"formatOptions\":{\"showIcon\":true}},{\"columnMatch\":\"deletions\",\"formatter\":4,\"formatOptions\":{\"showIcon\":true,\"aggregation\":\"Count\"}},{\"columnMatch\":\"creations\",\"formatter\":4,\"formatOptions\":{\"palette\":\"purple\",\"showIcon\":true,\"aggregation\":\"Count\"}},{\"columnMatch\":\"updates\",\"formatter\":4,\"formatOptions\":{\"palette\":\"gray\",\"showIcon\":true,\"aggregation\":\"Count\"}},{\"columnMatch\":\"Activities\",\"formatter\":4,\"formatOptions\":{\"palette\":\"greenDark\",\"linkTarget\":\"GenericDetails\",\"linkIsContextBlade\":true,\"showIcon\":true,\"aggregation\":\"Count\",\"workbookContext\":{\"componentIdSource\":\"workbook\",\"resourceIdsSource\":\"workbook\",\"templateIdSource\":\"static\",\"templateId\":\"https://go.microsoft.com/fwlink/?linkid=874159&resourceId=%2Fsubscriptions%2F44e4eff8-1fcb-4a22-a7d6-992ac7286382%2FresourceGroups%2FSOC&featureName=Workbooks&itemId=%2Fsubscriptions%2F44e4eff8-1fcb-4a22-a7d6-992ac7286382%2Fresourcegroups%2Fsoc%2Fproviders%2Fmicrosoft.insights%2Fworkbooks%2F4c195aec-747f-40bb-addb-934acb3ec646&name=CiscoASA&func=NavigateToPortalFeature&type=workbook\",\"typeSource\":\"workbook\",\"gallerySource\":\"workbook\"}}}],\"sortBy\":[{\"itemKey\":\"$gen_bar_updates_3\",\"sortOrder\":2}]}},\"name\":\"query - 1\"},{\"type\":3,\"content\":{\"version\":\"KqlItem/1.0\",\"query\":\"AzureActivity \\r\\n| where \\\"{Caller:lable}\\\" == \\\"All\\\" or Caller in ({Caller})\\r\\n| where \\\"{ResourceGroup:lable}\\\" == \\\"All\\\" or ResourceGroup in ({ResourceGroup})\\r\\n| summarize Informational = countif(Level == \\\"Informational\\\"), Warning = countif(Level == \\\"Warning\\\"), Error = countif(Level == \\\"Error\\\") by bin_at(TimeGenerated, 1h, now())\\r\\n\",\"size\":0,\"exportToExcelOptions\":\"visible\",\"title\":\"Activities by log level over time\",\"color\":\"redBright\",\"timeContext\":{\"durationMs\":0},\"timeContextFromParameter\":\"TimeRange\",\"queryType\":0,\"resourceType\":\"microsoft.operationalinsights/workspaces\",\"visualization\":\"scatterchart\",\"tileSettings\":{\"showBorder\":false},\"graphSettings\":{\"type\":2,\"topContent\":{\"columnMatch\":\"Error\",\"formatter\":12,\"formatOptions\":{\"showIcon\":true}},\"hivesContent\":{\"columnMatch\":\"TimeGenerated\",\"formatter\":1,\"formatOptions\":{\"showIcon\":true}},\"nodeIdField\":\"Error\",\"sourceIdField\":\"Error\",\"targetIdField\":\"Error\",\"staticNodeSize\":100,\"groupByField\":\"TimeGenerated\",\"hivesMargin\":5}},\"name\":\"query - 4\"}],\"fromTemplateId\":\"sentinel-AzureActivity\",\"$schema\":\"https://github.com/Microsoft/Application-Insights-Workbooks/blob/master/schema/workbook.json\"}\n", + "version": "1.0", + "sourceId": "[variables('workspaceResourceId')]", + "category": "sentinel" } }, { "type": "Microsoft.OperationalInsights/workspaces/providers/metadata", "apiVersion": "2022-01-01-preview", - "name": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/',concat('HuntingQuery-', last(split(variables('huntingQueryId1'),'/'))))]", + "name": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/',concat('Workbook-', last(split(variables('workbookId1'),'/'))))]", "properties": { - "description": "Azure Activity Hunting Query 1", - "parentId": "[variables('huntingQueryId1')]", - "contentId": "[variables('_huntingQuerycontentId1')]", - "kind": "HuntingQuery", - "version": "[variables('huntingQueryVersion1')]", + "description": "@{workbookKey=AzureActivityWorkbook; logoFileName=azureactivity_logo.svg; description=Gain extensive insight into your organization's Azure Activity by analyzing, and correlating all user operations and events.\nYou can learn about all user operations, trends, and anomalous changes over time.\nThis workbook gives you the ability to drill down into caller activities and summarize detected failure and warning events.; dataTypesDependencies=System.Object[]; dataConnectorsDependencies=System.Object[]; previewImagesFileNames=System.Object[]; version=2.0.0; title=Azure Activity; templateRelativePath=AzureActivity.json; subtitle=; provider=Microsoft}.description", + "parentId": "[variables('workbookId1')]", + "contentId": "[variables('_workbookContentId1')]", + "kind": "Workbook", + "version": "[variables('workbookVersion1')]", "source": { "kind": "Solution", "name": "Azure Activity", @@ -441,70 +435,108 @@ "name": "Microsoft Corporation", "email": "support@microsoft.com", "link": "https://support.microsoft.com/" + }, + "dependencies": { + "operator": "AND", + "criteria": [ + { + "contentId": "AzureActivity", + "kind": "DataType" + }, + { + "contentId": "AzureActivity", + "kind": "DataConnector" + } + ] } } } ] - } - } - }, - { - "type": "Microsoft.Resources/templateSpecs", - "apiVersion": "2022-02-01", - "name": "[variables('huntingQueryTemplateSpecName2')]", - "location": "[parameters('workspace-location')]", - "tags": { - "hidden-sentinelWorkspaceId": "[variables('workspaceResourceId')]", - "hidden-sentinelContentType": "HuntingQuery" - }, - "properties": { - "description": "Azure Activity Hunting Query 2 with template", - "displayName": "Azure Activity Hunting Query template" + }, + "packageKind": "Solution", + "packageVersion": "[variables('_solutionVersion')]", + "packageName": "[variables('_solutionName')]", + "packageId": "[variables('_solutionId')]", + "contentSchemaVersion": "3.0.0", + "contentId": "[variables('_workbookContentId1')]", + "contentKind": "Workbook", + "displayName": "[parameters('workbook1-name')]", + "contentProductId": "[variables('_workbookcontentProductId1')]", + "id": "[variables('_workbookcontentProductId1')]", + "version": "[variables('workbookVersion1')]" } }, { - "type": "Microsoft.Resources/templateSpecs/versions", - "apiVersion": "2022-02-01", - "name": "[concat(variables('huntingQueryTemplateSpecName2'),'/',variables('huntingQueryVersion2'))]", + "type": "Microsoft.OperationalInsights/workspaces/providers/contentTemplates", + "apiVersion": "2023-04-01-preview", + "name": "[variables('analyticRuleTemplateSpecName1')]", "location": "[parameters('workspace-location')]", - "tags": { - "hidden-sentinelWorkspaceId": "[variables('workspaceResourceId')]", - "hidden-sentinelContentType": "HuntingQuery" - }, "dependsOn": [ - "[resourceId('Microsoft.Resources/templateSpecs', variables('huntingQueryTemplateSpecName2'))]" + "[extensionResourceId(resourceId('Microsoft.OperationalInsights/workspaces', parameters('workspace')), 'Microsoft.SecurityInsights/contentPackages', variables('_solutionId'))]" ], "properties": { - "description": "AnomalousAzureOperationModel_HuntingQueries Hunting Query with template version 2.0.6", + "description": "AADHybridHealthADFSNewServer_AnalyticalRules Analytics Rule with template version 3.0.0", "mainTemplate": { "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", - "contentVersion": "[variables('huntingQueryVersion2')]", + "contentVersion": "[variables('analyticRuleVersion1')]", "parameters": {}, "variables": {}, "resources": [ { - "type": "Microsoft.OperationalInsights/savedSearches", - "apiVersion": "2020-08-01", - "name": "Azure_Activity_Hunting_Query_2", + "type": "Microsoft.SecurityInsights/AlertRuleTemplates", + "name": "[variables('analyticRulecontentId1')]", + "apiVersion": "2022-04-01-preview", + "kind": "Scheduled", "location": "[parameters('workspace-location')]", "properties": { - "eTag": "*", - "displayName": "Anomalous Azure Operation Hunting Model", - "category": "Hunting Queries", - "query": "// When the detection window will end (3 days prior to now)\nlet startDetectDate = 3d;\n// When the detection window will start (now)\nlet endDetectDate = 0d;\n// When to start collecting data for detection\nlet startDate = startDetectDate + 30d;\n// Operation to monitor, in this case Run Command\nlet monitoredOps = dynamic(['microsoft.compute/virtualmachines/runcommand/action']);\n// The resource type to monitor, in this case virtual machines\nlet monitoredResource = pack_array('microsoft.compute/virtualmachines');\nlet pair_probabilities_fl = (tbl:(*), A_col:string, B_col:string, scope_col:string)\n{\nlet T = (tbl | extend _A = column_ifexists(A_col, ''), _B = column_ifexists(B_col, ''), _scope = column_ifexists(scope_col, ''));\nlet countOnScope = T | summarize countAllOnScope = count() by _scope;\nlet probAB = T | summarize countAB = count() by _A, _B, _scope | join kind = leftouter (countOnScope) on _scope | extend P_AB = todouble(countAB)/countAllOnScope;\nlet probA = probAB | summarize countA = sum(countAB), countAllOnScope = max(countAllOnScope) by _A, _scope | extend P_A = todouble(countA)/countAllOnScope;\nlet probB = probAB | summarize countB = sum(countAB), countAllOnScope = max(countAllOnScope) by _B, _scope | extend P_B = todouble(countB)/countAllOnScope;\n probAB\n | join kind = leftouter (probA) on _A, _scope\n | join kind = leftouter (probB) on _B, _scope\n | extend P_AUB = P_A + P_B - P_AB\n , P_AIB = P_AB/P_B\n , P_BIA = P_AB/P_A\n | extend Lift_AB = P_AB/(P_A * P_B)\n , Jaccard_AB = P_AB/P_AUB\n | project _A, _B, _scope, floor(P_A, 0.00001), floor(P_B, 0.00001), floor(P_AB, 0.00001), floor(P_AUB, 0.00001), floor(P_AIB, 0.00001)\n , floor(P_BIA, 0.00001), floor(Lift_AB, 0.00001), floor(Jaccard_AB, 0.00001)\n | sort by _scope, _A, _B\n};\nlet eventsTable = materialize (\nAzureActivity\n| where TimeGenerated between (ago(startDate) .. ago(endDetectDate))\n| where isnotempty(CallerIpAddress)\n| where ActivityStatusValue has_any ('Success', 'Succeeded')\n| extend ResourceId = iff(isempty(_ResourceId), ResourceId, _ResourceId)\n| extend splitOp = split(OperationNameValue, '/')\n| extend splitRes = split(ResourceId, '/')\n| project TimeGenerated , subscriptionId=SubscriptionId\n , ResourceProvider\n , ResourceName = tolower(tostring(splitRes[-1]))\n , OperationNameValue = tolower(OperationNameValue)\n , timeSlice = floor(TimeGenerated, 1d)\n , clientIp = tostring(CallerIpAddress)\n , Caller\n , isMonitoredOp = iff(OperationNameValue has_any (monitoredOps), 1, 0)\n , isMonitoredResource = iff(OperationNameValue has_any (monitoredResource), 1, 0)\n , CorrelationId\n| extend clientIpMask = format_ipv4_mask(clientIp, 16)\n);\nlet modelData = (\neventsTable\n| where TimeGenerated < ago(startDetectDate) and isnotempty(Caller) and isnotempty(subscriptionId)\n| summarize countEvents = count(), countMonRes = countif(isMonitoredResource == 1), counMonOp = countif(isMonitoredOp == 1)\n , firstSeen = min(timeSlice), firstSeenOnMonRes = minif(timeSlice, isMonitoredResource == 1), firstSeenOnMonOp = minif(timeSlice, isMonitoredOp == 1)\n by subscriptionId, Caller, clientIpMask\n);\nlet monOpProbs = materialize (\neventsTable\n| where TimeGenerated < ago(startDetectDate) and isnotempty(Caller) and isnotempty(subscriptionId)\n| invoke pair_probabilities_fl('Caller', 'isMonitoredResource','subscriptionId')\n| where _B == 1\n| sort by P_AIB desc\n| extend rankOnMonRes = row_rank(P_AIB), sumBiggerCondProbs = row_cumsum(P_AIB) - P_AIB\n| extend avgBiggerCondProbs = floor(iff(rankOnMonRes > 1, sumBiggerCondProbs/(rankOnMonRes-1), max_of(0.0, prev(sumBiggerCondProbs))), 0.00001)\n| project-away sumBiggerCondProbs\n);\neventsTable\n| where TimeGenerated between (ago(startDetectDate) .. ago(endDetectDate))\n| join kind = leftouter (modelData | summarize countEventsPrincOnSub = sum(countEvents), countEventsMonResPrincOnSub = sum(countMonRes), countEventsMonOpPrincOnSub = sum(counMonOp)\n , firstSeenPrincOnSubs = min(firstSeen), firstSeenMonResPrincOnSubs = min(firstSeenOnMonRes), firstSeenMonOpPrincOnSubs = min(firstSeenOnMonOp) by subscriptionId, Caller) \n on subscriptionId, Caller\n| join kind = leftouter (modelData | summarize countEventsIpMaskOnSub = sum(countEvents), countEventsMonResIpMaskOnSub = sum(countMonRes), countEventsMonOpIpMaskOnSub = sum(counMonOp)\n , firstSeenIpMaskOnSubs = min(firstSeen), firstSeenMonResIpMaskOnSubs = min(firstSeenOnMonRes), firstSeenMonOpIpMaskOnSubs = min(firstSeenOnMonOp) by subscriptionId, clientIpMask) \n on subscriptionId, clientIpMask\n| join kind = leftouter (modelData | summarize countEventsOnSub = sum(countEvents), countEventsMonResOnSub = sum(countMonRes), countEventsMonOpOnSub = sum(counMonOp)\n , firstSeenOnSubs = min(firstSeen), firstSeenMonResOnSubs = min(firstSeenOnMonRes), firstSeenMonOpOnSubs = min(firstSeenOnMonOp)\n , countCallersOnSubs = dcount(Caller), countIpMasksOnSubs = dcount(clientIpMask) by subscriptionId)\n on subscriptionId \n| project-away subscriptionId1, Caller1, subscriptionId2\n| extend daysOnSubs = datetime_diff('day', timeSlice, firstSeenOnSubs)\n| extend avgMonOpOnSubs = floor(1.0*countEventsMonOpOnSub/daysOnSubs, 0.01), avgMonResOnSubs = floor(1.0*countEventsMonResOnSub/daysOnSubs, 0.01)\n| join kind = leftouter(monOpProbs) on $left.subscriptionId == $right._scope, $left.Caller == $right._A\n| project-away _A, _B, _scope\n| sort by subscriptionId asc, TimeGenerated asc\n| extend rnOnSubs = row_number(1, subscriptionId != prev(subscriptionId))\n| sort by subscriptionId asc, Caller asc, TimeGenerated asc\n| extend rnOnCallerSubs = row_number(1, (subscriptionId != prev(subscriptionId) and (Caller != prev(Caller))))\n| extend newCaller = iff(isempty(firstSeenPrincOnSubs), 1, 0)\n , newCallerOnMonRes = iff(isempty(firstSeenMonResPrincOnSubs), 1, 0)\n , newIpMask = iff(isempty(firstSeenIpMaskOnSubs), 1, 0)\n , newIpMaskOnMonRes = iff(isempty(firstSeenMonResIpMaskOnSubs), 1, 0)\n , newMonOpOnSubs = iff(isempty(firstSeenMonResOnSubs), 1, 0)\n , anomCallerMonRes = iff(((Jaccard_AB <= 0.1) or (P_AIB <= 0.1)), 1, 0)\n| project TimeGenerated, subscriptionId, ResourceProvider, ResourceName, OperationNameValue, Caller, CorrelationId, ClientIP=clientIp, ActiveDaysOnSub=daysOnSubs, avgMonOpOnSubs, newCaller, newCallerOnMonRes, newIpMask, newIpMaskOnMonRes, newMonOpOnSubs, anomCallerMonRes, isMonitoredOp, isMonitoredResource\n| order by TimeGenerated\n| where isMonitoredOp == 1\n// Optional - focus only on monitored operations or monitored resource in detection window\n| where isMonitoredOp == 1\n//| where isMonitoredResource == 1\n", - "version": 2, - "tags": [ + "description": "This detection uses AzureActivity logs (Administrative category) to identify the creation or update of a server instance in an Azure AD Hybrid Health AD FS service.\nA threat actor can create a new AD Health ADFS service and create a fake server instance to spoof AD FS signing logs. There is no need to compromise an on-premises AD FS server.\nThis can be done programmatically via HTTP requests to Azure. More information in this blog: https://o365blog.com/post/hybridhealthagent/", + "displayName": "Azure Active Directory Hybrid Health AD FS New Server", + "enabled": false, + "query": "AzureActivity\n| where CategoryValue =~ 'Administrative'\n| where ResourceProviderValue =~ 'Microsoft.ADHybridHealthService'\n| where _ResourceId has 'AdFederationService'\n| where OperationNameValue =~ 'Microsoft.ADHybridHealthService/services/servicemembers/action'\n| extend claimsJson = parse_json(Claims)\n| extend AppId = tostring(claimsJson.appid), AccountName = tostring(claimsJson.name), Name = tostring(split(Caller,'@',0)[0]), UPNSuffix = tostring(split(Caller,'@',1)[0])\n| project-away claimsJson\n", + "queryFrequency": "P1D", + "queryPeriod": "P1D", + "severity": "Medium", + "suppressionDuration": "PT1H", + "suppressionEnabled": false, + "triggerOperator": "GreaterThan", + "triggerThreshold": 0, + "status": "Available", + "requiredDataConnectors": [ { - "name": "description", - "value": "This query can be used during threat hunts to identify a range of different Azure Operation anomalies.\nThe query is heavily commented inline to explain operation. Anomalies covered are: New Caller, New Caller IP,\nNew Caller IP Range, Anomalous operation based on Jaccard index. By default this query is configured to detect\nanomalous Run Command operations. The operation and resource type to perform anomaly detection can be configured \nat the top of the query along with the detection window parameters" - }, + "connectorId": "AzureActivity", + "dataTypes": [ + "AzureActivity" + ] + } + ], + "tactics": [ + "DefenseEvasion" + ], + "techniques": [ + "T1578" + ], + "entityMappings": [ { - "name": "tactics", - "value": "LateralMovement,CredentialAccess" + "fieldMappings": [ + { + "identifier": "Name", + "columnName": "Name" + }, + { + "identifier": "UPNSuffix", + "columnName": "UPNSuffix" + } + ], + "entityType": "Account" }, { - "name": "techniques", - "value": "T1570,T1078.004" + "fieldMappings": [ + { + "identifier": "Address", + "columnName": "CallerIpAddress" + } + ], + "entityType": "IP" } ] } @@ -512,13 +544,13 @@ { "type": "Microsoft.OperationalInsights/workspaces/providers/metadata", "apiVersion": "2022-01-01-preview", - "name": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/',concat('HuntingQuery-', last(split(variables('huntingQueryId2'),'/'))))]", + "name": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/',concat('AnalyticsRule-', last(split(variables('analyticRuleId1'),'/'))))]", "properties": { - "description": "Azure Activity Hunting Query 2", - "parentId": "[variables('huntingQueryId2')]", - "contentId": "[variables('_huntingQuerycontentId2')]", - "kind": "HuntingQuery", - "version": "[variables('huntingQueryVersion2')]", + "description": "Azure Activity Analytics Rule 1", + "parentId": "[variables('analyticRuleId1')]", + "contentId": "[variables('_analyticRulecontentId1')]", + "kind": "AnalyticsRule", + "version": "[variables('analyticRuleVersion1')]", "source": { "kind": "Solution", "name": "Azure Activity", @@ -537,66 +569,91 @@ } } ] - } - } - }, - { - "type": "Microsoft.Resources/templateSpecs", - "apiVersion": "2022-02-01", - "name": "[variables('huntingQueryTemplateSpecName3')]", - "location": "[parameters('workspace-location')]", - "tags": { - "hidden-sentinelWorkspaceId": "[variables('workspaceResourceId')]", - "hidden-sentinelContentType": "HuntingQuery" - }, - "properties": { - "description": "Azure Activity Hunting Query 3 with template", - "displayName": "Azure Activity Hunting Query template" + }, + "packageKind": "Solution", + "packageVersion": "[variables('_solutionVersion')]", + "packageName": "[variables('_solutionName')]", + "packageId": "[variables('_solutionId')]", + "contentSchemaVersion": "3.0.0", + "contentId": "[variables('_analyticRulecontentId1')]", + "contentKind": "AnalyticsRule", + "displayName": "Azure Active Directory Hybrid Health AD FS New Server", + "contentProductId": "[variables('_analyticRulecontentProductId1')]", + "id": "[variables('_analyticRulecontentProductId1')]", + "version": "[variables('analyticRuleVersion1')]" } }, { - "type": "Microsoft.Resources/templateSpecs/versions", - "apiVersion": "2022-02-01", - "name": "[concat(variables('huntingQueryTemplateSpecName3'),'/',variables('huntingQueryVersion3'))]", + "type": "Microsoft.OperationalInsights/workspaces/providers/contentTemplates", + "apiVersion": "2023-04-01-preview", + "name": "[variables('analyticRuleTemplateSpecName2')]", "location": "[parameters('workspace-location')]", - "tags": { - "hidden-sentinelWorkspaceId": "[variables('workspaceResourceId')]", - "hidden-sentinelContentType": "HuntingQuery" - }, "dependsOn": [ - "[resourceId('Microsoft.Resources/templateSpecs', variables('huntingQueryTemplateSpecName3'))]" + "[extensionResourceId(resourceId('Microsoft.OperationalInsights/workspaces', parameters('workspace')), 'Microsoft.SecurityInsights/contentPackages', variables('_solutionId'))]" ], "properties": { - "description": "Anomalous_Listing_Of_Storage_Keys_HuntingQueries Hunting Query with template version 2.0.6", + "description": "AADHybridHealthADFSServiceDelete_AnalyticalRules Analytics Rule with template version 3.0.0", "mainTemplate": { "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", - "contentVersion": "[variables('huntingQueryVersion3')]", + "contentVersion": "[variables('analyticRuleVersion2')]", "parameters": {}, "variables": {}, "resources": [ { - "type": "Microsoft.OperationalInsights/savedSearches", - "apiVersion": "2020-08-01", - "name": "Azure_Activity_Hunting_Query_3", + "type": "Microsoft.SecurityInsights/AlertRuleTemplates", + "name": "[variables('analyticRulecontentId2')]", + "apiVersion": "2022-04-01-preview", + "kind": "Scheduled", "location": "[parameters('workspace-location')]", "properties": { - "eTag": "*", - "displayName": "Azure storage key enumeration", - "category": "Hunting Queries", - "query": "AzureActivity\n| where OperationNameValue =~ \"microsoft.storage/storageaccounts/listkeys/action\"\n| where ActivityStatusValue =~ \"Succeeded\" \n| join kind= inner (\n AzureActivity\n | where OperationNameValue =~ \"microsoft.storage/storageaccounts/listkeys/action\"\n | where ActivityStatusValue =~ \"Succeeded\" \n | project ExpectedIpAddress=CallerIpAddress, Caller \n | evaluate autocluster()\n) on Caller\n| where CallerIpAddress != ExpectedIpAddress\n| summarize StartTime = min(TimeGenerated), EndTime = max(TimeGenerated), ResourceIds = make_set(ResourceId,100), ResourceIdCount = dcount(ResourceId) by OperationNameValue, Caller, CallerIpAddress\n| extend Name = tostring(split(Caller,'@',0)[0]), UPNSuffix = tostring(split(Caller,'@',1)[0])\n| extend Account_0_Name = Name\n| extend Account_0_UPNSuffix = UPNSuffix\n| extend IP_0_Address = CallerIpAddress\n", - "version": 2, - "tags": [ + "description": "This detection uses AzureActivity logs (Administrative category) to identify the deletion of an Azure AD Hybrid Health AD FS service instance in a tenant.\nA threat actor can create a new AD Health ADFS service and create a fake server to spoof AD FS signing logs.\nThe health AD FS service can then be deleted after it is no longer needed via HTTP requests to Azure.\nMore information is available in this blog https://o365blog.com/post/hybridhealthagent/", + "displayName": "Azure Active Directory Hybrid Health AD FS Service Delete", + "enabled": false, + "query": "AzureActivity\n| where CategoryValue =~ 'Administrative'\n| where ResourceProviderValue =~ 'Microsoft.ADHybridHealthService'\n| where _ResourceId has 'AdFederationService'\n| where OperationNameValue =~ 'Microsoft.ADHybridHealthService/services/delete'\n| extend claimsJson = parse_json(Claims)\n| extend AppId = tostring(claimsJson.appid), AccountName = tostring(claimsJson.name), Name = tostring(split(Caller,'@',0)[0]), UPNSuffix = tostring(split(Caller,'@',1)[0])\n| project-away claimsJson\n", + "queryFrequency": "P1D", + "queryPeriod": "P1D", + "severity": "Medium", + "suppressionDuration": "PT1H", + "suppressionEnabled": false, + "triggerOperator": "GreaterThan", + "triggerThreshold": 0, + "status": "Available", + "requiredDataConnectors": [ { - "name": "description", - "value": "Listing of storage keys is an interesting operation in Azure which might expose additional \nsecrets and PII to callers as well as granting access to VMs. While there are many benign operations of this\ntype, it would be interesting to see if the account performing this activity or the source IP address from \nwhich it is being done is anomalous. \nThe query below generates known clusters of ip address per caller, notice that users which only had single\noperations do not appear in this list as we cannot learn from it their normal activity (only based on a single\nevent). The activities for listing storage account keys is correlated with this learned \nclusters of expected activities and activity which is not expected is returned." - }, + "connectorId": "AzureActivity", + "dataTypes": [ + "AzureActivity" + ] + } + ], + "tactics": [ + "DefenseEvasion" + ], + "techniques": [ + "T1578" + ], + "entityMappings": [ { - "name": "tactics", - "value": "Discovery" + "fieldMappings": [ + { + "identifier": "Name", + "columnName": "Name" + }, + { + "identifier": "UPNSuffix", + "columnName": "UPNSuffix" + } + ], + "entityType": "Account" }, { - "name": "techniques", - "value": "T1087" + "fieldMappings": [ + { + "identifier": "Address", + "columnName": "CallerIpAddress" + } + ], + "entityType": "IP" } ] } @@ -604,13 +661,13 @@ { "type": "Microsoft.OperationalInsights/workspaces/providers/metadata", "apiVersion": "2022-01-01-preview", - "name": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/',concat('HuntingQuery-', last(split(variables('huntingQueryId3'),'/'))))]", + "name": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/',concat('AnalyticsRule-', last(split(variables('analyticRuleId2'),'/'))))]", "properties": { - "description": "Azure Activity Hunting Query 3", - "parentId": "[variables('huntingQueryId3')]", - "contentId": "[variables('_huntingQuerycontentId3')]", - "kind": "HuntingQuery", - "version": "[variables('huntingQueryVersion3')]", + "description": "Azure Activity Analytics Rule 2", + "parentId": "[variables('analyticRuleId2')]", + "contentId": "[variables('_analyticRulecontentId2')]", + "kind": "AnalyticsRule", + "version": "[variables('analyticRuleVersion2')]", "source": { "kind": "Solution", "name": "Azure Activity", @@ -629,66 +686,93 @@ } } ] - } - } - }, - { - "type": "Microsoft.Resources/templateSpecs", - "apiVersion": "2022-02-01", - "name": "[variables('huntingQueryTemplateSpecName4')]", - "location": "[parameters('workspace-location')]", - "tags": { - "hidden-sentinelWorkspaceId": "[variables('workspaceResourceId')]", - "hidden-sentinelContentType": "HuntingQuery" - }, - "properties": { - "description": "Azure Activity Hunting Query 4 with template", - "displayName": "Azure Activity Hunting Query template" + }, + "packageKind": "Solution", + "packageVersion": "[variables('_solutionVersion')]", + "packageName": "[variables('_solutionName')]", + "packageId": "[variables('_solutionId')]", + "contentSchemaVersion": "3.0.0", + "contentId": "[variables('_analyticRulecontentId2')]", + "contentKind": "AnalyticsRule", + "displayName": "Azure Active Directory Hybrid Health AD FS Service Delete", + "contentProductId": "[variables('_analyticRulecontentProductId2')]", + "id": "[variables('_analyticRulecontentProductId2')]", + "version": "[variables('analyticRuleVersion2')]" } }, { - "type": "Microsoft.Resources/templateSpecs/versions", - "apiVersion": "2022-02-01", - "name": "[concat(variables('huntingQueryTemplateSpecName4'),'/',variables('huntingQueryVersion4'))]", + "type": "Microsoft.OperationalInsights/workspaces/providers/contentTemplates", + "apiVersion": "2023-04-01-preview", + "name": "[variables('analyticRuleTemplateSpecName3')]", "location": "[parameters('workspace-location')]", - "tags": { - "hidden-sentinelWorkspaceId": "[variables('workspaceResourceId')]", - "hidden-sentinelContentType": "HuntingQuery" - }, "dependsOn": [ - "[resourceId('Microsoft.Resources/templateSpecs', variables('huntingQueryTemplateSpecName4'))]" + "[extensionResourceId(resourceId('Microsoft.OperationalInsights/workspaces', parameters('workspace')), 'Microsoft.SecurityInsights/contentPackages', variables('_solutionId'))]" ], "properties": { - "description": "AzureAdministrationFromVPS_HuntingQueries Hunting Query with template version 2.0.6", + "description": "AADHybridHealthADFSSuspApp_AnalyticalRules Analytics Rule with template version 3.0.0", "mainTemplate": { "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", - "contentVersion": "[variables('huntingQueryVersion4')]", + "contentVersion": "[variables('analyticRuleVersion3')]", "parameters": {}, "variables": {}, "resources": [ { - "type": "Microsoft.OperationalInsights/savedSearches", - "apiVersion": "2020-08-01", - "name": "Azure_Activity_Hunting_Query_4", + "type": "Microsoft.SecurityInsights/AlertRuleTemplates", + "name": "[variables('analyticRulecontentId3')]", + "apiVersion": "2022-04-01-preview", + "kind": "Scheduled", "location": "[parameters('workspace-location')]", "properties": { - "eTag": "*", - "displayName": "AzureActivity Administration From VPS Providers", - "category": "Hunting Queries", - "query": "let IP_Data = (externaldata(network:string)\n[@\"https://raw.githubusercontent.com/Azure/Azure-Sentinel/master/Sample%20Data/Feeds/VPS_Networks.csv\"] with (format=\"csv\"));\nAzureActivity\n| where CategoryValue =~ \"Administrative\"\n| evaluate ipv4_lookup(IP_Data, CallerIpAddress, network, return_unmatched = false)\n| summarize Operations = make_set(OperationNameValue), StartTime = min(TimeGenerated), EndTime = max(TimeGenerated) by CallerIpAddress, Caller\n| extend Name = tostring(split(Caller,'@',0)[0]), UPNSuffix = tostring(split(Caller,'@',1)[0])\n| extend Account_0_Name = Name\n| extend Account_0_UPNSuffix = UPNSuffix\n| extend IP_0_Address = CallerIpAddress\n", - "version": 2, - "tags": [ + "description": "This detection uses AzureActivity logs (Administrative category) to identify a suspicious application adding a server instance to an Azure AD Hybrid Health AD FS service or deleting the AD FS service instance.\nUsually the Azure AD Connect Health Agent application with ID cf6d7e68-f018-4e0a-a7b3-126e053fb88d and ID cb1056e2-e479-49de-ae31-7812af012ed8 is used to perform those operations.", + "displayName": "Azure Active Directory Hybrid Health AD FS Suspicious Application", + "enabled": false, + "query": "// Azure AD Connect Health Agent - cf6d7e68-f018-4e0a-a7b3-126e053fb88d\n// Azure Active Directory Connect - cb1056e2-e479-49de-ae31-7812af012ed8\nlet appList = dynamic(['cf6d7e68-f018-4e0a-a7b3-126e053fb88d','cb1056e2-e479-49de-ae31-7812af012ed8']);\nlet operationNamesList = dynamic(['Microsoft.ADHybridHealthService/services/servicemembers/action','Microsoft.ADHybridHealthService/services/delete']);\nAzureActivity\n| where CategoryValue =~ 'Administrative'\n| where ResourceProviderValue =~ 'Microsoft.ADHybridHealthService'\n| where _ResourceId has 'AdFederationService'\n| where OperationNameValue in~ (operationNamesList)\n| extend claimsJson = parse_json(Claims)\n| extend AppId = tostring(claimsJson.appid), AccountName = tostring(claimsJson.name), Name = tostring(split(Caller,'@',0)[0]), UPNSuffix = tostring(split(Caller,'@',1)[0])\n| where AppId !in (appList)\n| project-away claimsJson\n", + "queryFrequency": "P1D", + "queryPeriod": "P1D", + "severity": "Medium", + "suppressionDuration": "PT1H", + "suppressionEnabled": false, + "triggerOperator": "GreaterThan", + "triggerThreshold": 0, + "status": "Available", + "requiredDataConnectors": [ { - "name": "description", - "value": "Looks for administrative actions in AzureActivity from known VPS provider network ranges.\nThis is not an exhaustive list of VPS provider ranges but covers some of the most prevalent providers observed." - }, + "connectorId": "AzureActivity", + "dataTypes": [ + "AzureActivity" + ] + } + ], + "tactics": [ + "CredentialAccess", + "DefenseEvasion" + ], + "techniques": [ + "T1528", + "T1550" + ], + "entityMappings": [ { - "name": "tactics", - "value": "InitialAccess" + "fieldMappings": [ + { + "identifier": "Name", + "columnName": "Name" + }, + { + "identifier": "UPNSuffix", + "columnName": "UPNSuffix" + } + ], + "entityType": "Account" }, { - "name": "techniques", - "value": "T1078" + "fieldMappings": [ + { + "identifier": "Address", + "columnName": "CallerIpAddress" + } + ], + "entityType": "IP" } ] } @@ -696,13 +780,13 @@ { "type": "Microsoft.OperationalInsights/workspaces/providers/metadata", "apiVersion": "2022-01-01-preview", - "name": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/',concat('HuntingQuery-', last(split(variables('huntingQueryId4'),'/'))))]", + "name": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/',concat('AnalyticsRule-', last(split(variables('analyticRuleId3'),'/'))))]", "properties": { - "description": "Azure Activity Hunting Query 4", - "parentId": "[variables('huntingQueryId4')]", - "contentId": "[variables('_huntingQuerycontentId4')]", - "kind": "HuntingQuery", - "version": "[variables('huntingQueryVersion4')]", + "description": "Azure Activity Analytics Rule 3", + "parentId": "[variables('analyticRuleId3')]", + "contentId": "[variables('_analyticRulecontentId3')]", + "kind": "AnalyticsRule", + "version": "[variables('analyticRuleVersion3')]", "source": { "kind": "Solution", "name": "Azure Activity", @@ -721,66 +805,95 @@ } } ] - } - } - }, - { - "type": "Microsoft.Resources/templateSpecs", - "apiVersion": "2022-02-01", - "name": "[variables('huntingQueryTemplateSpecName5')]", - "location": "[parameters('workspace-location')]", - "tags": { - "hidden-sentinelWorkspaceId": "[variables('workspaceResourceId')]", - "hidden-sentinelContentType": "HuntingQuery" - }, - "properties": { - "description": "Azure Activity Hunting Query 5 with template", - "displayName": "Azure Activity Hunting Query template" + }, + "packageKind": "Solution", + "packageVersion": "[variables('_solutionVersion')]", + "packageName": "[variables('_solutionName')]", + "packageId": "[variables('_solutionId')]", + "contentSchemaVersion": "3.0.0", + "contentId": "[variables('_analyticRulecontentId3')]", + "contentKind": "AnalyticsRule", + "displayName": "Azure Active Directory Hybrid Health AD FS Suspicious Application", + "contentProductId": "[variables('_analyticRulecontentProductId3')]", + "id": "[variables('_analyticRulecontentProductId3')]", + "version": "[variables('analyticRuleVersion3')]" } }, { - "type": "Microsoft.Resources/templateSpecs/versions", - "apiVersion": "2022-02-01", - "name": "[concat(variables('huntingQueryTemplateSpecName5'),'/',variables('huntingQueryVersion5'))]", + "type": "Microsoft.OperationalInsights/workspaces/providers/contentTemplates", + "apiVersion": "2023-04-01-preview", + "name": "[variables('analyticRuleTemplateSpecName4')]", "location": "[parameters('workspace-location')]", - "tags": { - "hidden-sentinelWorkspaceId": "[variables('workspaceResourceId')]", - "hidden-sentinelContentType": "HuntingQuery" - }, "dependsOn": [ - "[resourceId('Microsoft.Resources/templateSpecs', variables('huntingQueryTemplateSpecName5'))]" + "[extensionResourceId(resourceId('Microsoft.OperationalInsights/workspaces', parameters('workspace')), 'Microsoft.SecurityInsights/contentPackages', variables('_solutionId'))]" ], "properties": { - "description": "AzureNSG_AdministrativeOperations_HuntingQueries Hunting Query with template version 2.0.6", + "description": "Creating_Anomalous_Number_Of_Resources_detection_AnalyticalRules Analytics Rule with template version 3.0.0", "mainTemplate": { "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", - "contentVersion": "[variables('huntingQueryVersion5')]", + "contentVersion": "[variables('analyticRuleVersion4')]", "parameters": {}, "variables": {}, "resources": [ { - "type": "Microsoft.OperationalInsights/savedSearches", - "apiVersion": "2020-08-01", - "name": "Azure_Activity_Hunting_Query_5", + "type": "Microsoft.SecurityInsights/AlertRuleTemplates", + "name": "[variables('analyticRulecontentId4')]", + "apiVersion": "2022-04-01-preview", + "kind": "Scheduled", "location": "[parameters('workspace-location')]", "properties": { - "eTag": "*", - "displayName": "Azure Network Security Group NSG Administrative Operations", - "category": "Hunting Queries", - "query": "let opValues = dynamic([\"Microsoft.Network/networkSecurityGroups/write\", \"Microsoft.Network/networkSecurityGroups/delete\"]);\n// Azure NSG Create / Update / Delete\nAzureActivity\n| where Category =~ \"Administrative\"\n| where OperationNameValue in~ (opValues)\n| where ActivitySubstatusValue in~ (\"Created\", \"OK\",\"Accepted\")\n| sort by TimeGenerated desc\n| extend Name = tostring(split(Caller,'@',0)[0]), UPNSuffix = tostring(split(Caller,'@',1)[0])\n| extend Account_0_Name = Name\n| extend Account_0_UPNSuffix = UPNSuffix\n| extend IP_0_Address = CallerIpAddress\n", - "version": 2, - "tags": [ + "description": "Indicates when an anomalous number of VM creations or deployment activities occur in Azure via the AzureActivity log. This query generates the baseline pattern of cloud resource creation by an individual and generates an anomaly when any unusual spike is detected. These anomalies from unusual or privileged users could be an indication of a cloud infrastructure takedown by an adversary.", + "displayName": "Suspicious number of resource creation or deployment activities", + "enabled": false, + "query": "let szOperationNames = dynamic([\"microsoft.compute/virtualMachines/write\", \"microsoft.resources/deployments/write\"]);\nlet starttime = 7d;\nlet endtime = 1d;\nlet timeframe = 1d;\nlet TimeSeriesData =\nAzureActivity\n| where TimeGenerated between (startofday(ago(starttime)) .. startofday(now()))\n| where OperationNameValue in~ (szOperationNames)\n| project TimeGenerated, Caller \n| make-series Total = count() on TimeGenerated from startofday(ago(starttime)) to startofday(now()) step timeframe by Caller; \nTimeSeriesData\n| extend (anomalies, score, baseline) = series_decompose_anomalies(Total, 3, -1, 'linefit')\n| mv-expand Total to typeof(double), TimeGenerated to typeof(datetime), anomalies to typeof(double), score to typeof(double), baseline to typeof(long) \n| where TimeGenerated >= startofday(ago(endtime))\n| where anomalies > 0 and baseline > 0\n| project Caller, TimeGenerated, Total, baseline, anomalies, score\n| join (AzureActivity\n| where TimeGenerated > startofday(ago(endtime)) \n| where OperationNameValue in~ (szOperationNames)\n| summarize make_set(OperationNameValue,100), make_set(_ResourceId,100), make_set(CallerIpAddress,100) by bin(TimeGenerated, timeframe), Caller\n) on TimeGenerated, Caller\n| mv-expand CallerIpAddress=set_CallerIpAddress\n| project-away Caller1\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 '@',Caller,\"\")\n", + "queryFrequency": "P1D", + "queryPeriod": "P7D", + "severity": "Medium", + "suppressionDuration": "PT1H", + "suppressionEnabled": false, + "triggerOperator": "GreaterThan", + "triggerThreshold": 0, + "status": "Available", + "requiredDataConnectors": [ { - "name": "description", - "value": "Identifies a set of Azure NSG administrative and operational detection queries for hunting activities." - }, + "connectorId": "AzureActivity", + "dataTypes": [ + "AzureActivity" + ] + } + ], + "tactics": [ + "Impact" + ], + "techniques": [ + "T1496" + ], + "entityMappings": [ { - "name": "tactics", - "value": "Impact" + "fieldMappings": [ + { + "identifier": "Name", + "columnName": "Name" + }, + { + "identifier": "UPNSuffix", + "columnName": "UPNSuffix" + }, + { + "identifier": "AadUserId", + "columnName": "AadUserId" + } + ], + "entityType": "Account" }, { - "name": "techniques", - "value": "T1496" + "fieldMappings": [ + { + "identifier": "Address", + "columnName": "CallerIpAddress" + } + ], + "entityType": "IP" } ] } @@ -788,13 +901,13 @@ { "type": "Microsoft.OperationalInsights/workspaces/providers/metadata", "apiVersion": "2022-01-01-preview", - "name": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/',concat('HuntingQuery-', last(split(variables('huntingQueryId5'),'/'))))]", + "name": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/',concat('AnalyticsRule-', last(split(variables('analyticRuleId4'),'/'))))]", "properties": { - "description": "Azure Activity Hunting Query 5", - "parentId": "[variables('huntingQueryId5')]", - "contentId": "[variables('_huntingQuerycontentId5')]", - "kind": "HuntingQuery", - "version": "[variables('huntingQueryVersion5')]", + "description": "Azure Activity Analytics Rule 4", + "parentId": "[variables('analyticRuleId4')]", + "contentId": "[variables('_analyticRulecontentId4')]", + "kind": "AnalyticsRule", + "version": "[variables('analyticRuleVersion4')]", "source": { "kind": "Solution", "name": "Azure Activity", @@ -813,66 +926,100 @@ } } ] - } - } - }, - { - "type": "Microsoft.Resources/templateSpecs", - "apiVersion": "2022-02-01", - "name": "[variables('huntingQueryTemplateSpecName6')]", - "location": "[parameters('workspace-location')]", - "tags": { - "hidden-sentinelWorkspaceId": "[variables('workspaceResourceId')]", - "hidden-sentinelContentType": "HuntingQuery" - }, - "properties": { - "description": "Azure Activity Hunting Query 6 with template", - "displayName": "Azure Activity Hunting Query template" + }, + "packageKind": "Solution", + "packageVersion": "[variables('_solutionVersion')]", + "packageName": "[variables('_solutionName')]", + "packageId": "[variables('_solutionId')]", + "contentSchemaVersion": "3.0.0", + "contentId": "[variables('_analyticRulecontentId4')]", + "contentKind": "AnalyticsRule", + "displayName": "Suspicious number of resource creation or deployment activities", + "contentProductId": "[variables('_analyticRulecontentProductId4')]", + "id": "[variables('_analyticRulecontentProductId4')]", + "version": "[variables('analyticRuleVersion4')]" } }, { - "type": "Microsoft.Resources/templateSpecs/versions", - "apiVersion": "2022-02-01", - "name": "[concat(variables('huntingQueryTemplateSpecName6'),'/',variables('huntingQueryVersion6'))]", + "type": "Microsoft.OperationalInsights/workspaces/providers/contentTemplates", + "apiVersion": "2023-04-01-preview", + "name": "[variables('analyticRuleTemplateSpecName5')]", "location": "[parameters('workspace-location')]", - "tags": { - "hidden-sentinelWorkspaceId": "[variables('workspaceResourceId')]", - "hidden-sentinelContentType": "HuntingQuery" - }, "dependsOn": [ - "[resourceId('Microsoft.Resources/templateSpecs', variables('huntingQueryTemplateSpecName6'))]" + "[extensionResourceId(resourceId('Microsoft.OperationalInsights/workspaces', parameters('workspace')), 'Microsoft.SecurityInsights/contentPackages', variables('_solutionId'))]" ], "properties": { - "description": "AzureRunCommandFromAzureIP_HuntingQueries Hunting Query with template version 2.0.6", + "description": "Creation_of_Expensive_Computes_in_Azure_AnalyticalRules Analytics Rule with template version 3.0.0", "mainTemplate": { "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", - "contentVersion": "[variables('huntingQueryVersion6')]", + "contentVersion": "[variables('analyticRuleVersion5')]", "parameters": {}, "variables": {}, "resources": [ { - "type": "Microsoft.OperationalInsights/savedSearches", - "apiVersion": "2020-08-01", - "name": "Azure_Activity_Hunting_Query_6", + "type": "Microsoft.SecurityInsights/AlertRuleTemplates", + "name": "[variables('analyticRulecontentId5')]", + "apiVersion": "2022-04-01-preview", + "kind": "Scheduled", "location": "[parameters('workspace-location')]", "properties": { - "eTag": "*", - "displayName": "Azure VM Run Command executed from Azure IP address", - "category": "Hunting Queries", - "query": "let azure_ranges = externaldata(changeNumber: string, cloud: string, values: dynamic)\n[\"https://raw.githubusercontent.com/microsoft/mstic/master/PublicFeeds/MSFTIPRanges/ServiceTags_Public.json\"] with(format='multijson')\n| mv-expand values\n| extend Name = values.name, AddressPrefixes = values.properties.addressPrefixes\n| where Name startswith \"WindowsVirtualDesktop\"\n| mv-expand AddressPrefixes\n| summarize by tostring(AddressPrefixes);\nAzureActivity\n| where TimeGenerated > ago(30d)\n// Isolate run command actions\n| where OperationNameValue == \"Microsoft.Compute/virtualMachines/runCommand/action\"\n// Confirm that the operation impacted a virtual machine\n| where Authorization has \"virtualMachines\"\n// Each runcommand operation consists of three events when successful, Started, Accepted (or Rejected), Successful (or Failed).\n| summarize StartTime=min(TimeGenerated), EndTime=max(TimeGenerated), max(CallerIpAddress), make_list(ActivityStatusValue) by CorrelationId, Authorization, Caller\n// Limit to Run Command executions that Succeeded\n| where list_ActivityStatusValue has \"Succeeded\"\n// Extract data from the Authorization field, allowing us to later extract the Caller (UPN) and CallerIpAddress\n| extend Authorization_d = parse_json(Authorization)\n| extend Scope = Authorization_d.scope\n| extend Scope_s = split(Scope, \"/\")\n| extend Subscription = tostring(Scope_s[2])\n| extend VirtualMachineName = tostring(Scope_s[-1])\n| project StartTime, EndTime, Subscription, VirtualMachineName, CorrelationId, Caller, CallerIpAddress=max_CallerIpAddress\n| evaluate ipv4_lookup(azure_ranges, CallerIpAddress, AddressPrefixes)\n| extend IP_0_Address = CallerIpAddress\n", - "version": 2, - "tags": [ + "description": "Identifies the creation of large size or expensive VMs (with GPUs or with a large number of virtual CPUs) in Azure.\nAn adversary may create new or update existing virtual machines to evade defenses or use them for cryptomining purposes.\nFor Windows/Linux Vm Sizes, see https://docs.microsoft.com/azure/virtual-machines/windows/sizes \nAzure VM Naming Conventions, see https://docs.microsoft.com/azure/virtual-machines/vm-naming-conventions", + "displayName": "Creation of expensive computes in Azure", + "enabled": false, + "query": "let tokens = dynamic([\"416\",\"208\",\"192\",\"128\",\"120\",\"96\",\"80\",\"72\",\"64\",\"48\",\"44\",\"40\",\"nc12\",\"nc24\",\"nv24\"]);\nlet operationList = dynamic([\"microsoft.compute/virtualmachines/write\", \"microsoft.resources/deployments/write\"]);\nAzureActivity\n| where OperationNameValue in~ (operationList)\n| where ActivityStatusValue startswith \"Accept\"\n| where Properties has 'vmSize'\n| extend parsed_property= parse_json(tostring((parse_json(Properties).responseBody))).properties\n| extend vmSize = tostring((parsed_property.hardwareProfile).vmSize)\n| mv-apply token=tokens to typeof(string) on (where vmSize contains token)\n| extend ComputerName = tostring((parsed_property.osProfile).computerName)\n| project TimeGenerated, OperationNameValue, ActivityStatusValue, Caller, CallerIpAddress, ComputerName, vmSize\n| extend Name = tostring(split(Caller,'@',0)[0]), UPNSuffix = tostring(split(Caller,'@',1)[0])\n", + "queryFrequency": "P1D", + "queryPeriod": "P1D", + "severity": "Low", + "suppressionDuration": "PT1H", + "suppressionEnabled": false, + "triggerOperator": "GreaterThan", + "triggerThreshold": 1, + "status": "Available", + "requiredDataConnectors": [ { - "name": "description", - "value": "Identifies any Azure VM Run Command operation executed from an Azure IP address.\nRun Command allows an attacker or legitimate user to execute arbitrary PowerShell\non a target VM. This technique has been seen in use by NOBELIUM." + "connectorId": "AzureActivity", + "dataTypes": [ + "AzureActivity" + ] + } + ], + "tactics": [ + "DefenseEvasion" + ], + "techniques": [ + "T1578" + ], + "entityMappings": [ + { + "fieldMappings": [ + { + "identifier": "Name", + "columnName": "Name" + }, + { + "identifier": "UPNSuffix", + "columnName": "UPNSuffix" + } + ], + "entityType": "Account" }, { - "name": "tactics", - "value": "LateralMovement,CredentialAccess" + "fieldMappings": [ + { + "identifier": "HostName", + "columnName": "ComputerName" + } + ], + "entityType": "Host" }, { - "name": "techniques", - "value": "T1570,T1078.004" + "fieldMappings": [ + { + "identifier": "Address", + "columnName": "CallerIpAddress" + } + ], + "entityType": "IP" } ] } @@ -880,13 +1027,13 @@ { "type": "Microsoft.OperationalInsights/workspaces/providers/metadata", "apiVersion": "2022-01-01-preview", - "name": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/',concat('HuntingQuery-', last(split(variables('huntingQueryId6'),'/'))))]", + "name": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/',concat('AnalyticsRule-', last(split(variables('analyticRuleId5'),'/'))))]", "properties": { - "description": "Azure Activity Hunting Query 6", - "parentId": "[variables('huntingQueryId6')]", - "contentId": "[variables('_huntingQuerycontentId6')]", - "kind": "HuntingQuery", - "version": "[variables('huntingQueryVersion6')]", + "description": "Azure Activity Analytics Rule 5", + "parentId": "[variables('analyticRuleId5')]", + "contentId": "[variables('_analyticRulecontentId5')]", + "kind": "AnalyticsRule", + "version": "[variables('analyticRuleVersion5')]", "source": { "kind": "Solution", "name": "Azure Activity", @@ -905,66 +1052,99 @@ } } ] - } - } - }, - { - "type": "Microsoft.Resources/templateSpecs", - "apiVersion": "2022-02-01", - "name": "[variables('huntingQueryTemplateSpecName7')]", - "location": "[parameters('workspace-location')]", - "tags": { - "hidden-sentinelWorkspaceId": "[variables('workspaceResourceId')]", - "hidden-sentinelContentType": "HuntingQuery" - }, - "properties": { - "description": "Azure Activity Hunting Query 7 with template", - "displayName": "Azure Activity Hunting Query template" + }, + "packageKind": "Solution", + "packageVersion": "[variables('_solutionVersion')]", + "packageName": "[variables('_solutionName')]", + "packageId": "[variables('_solutionId')]", + "contentSchemaVersion": "3.0.0", + "contentId": "[variables('_analyticRulecontentId5')]", + "contentKind": "AnalyticsRule", + "displayName": "Creation of expensive computes in Azure", + "contentProductId": "[variables('_analyticRulecontentProductId5')]", + "id": "[variables('_analyticRulecontentProductId5')]", + "version": "[variables('analyticRuleVersion5')]" } }, { - "type": "Microsoft.Resources/templateSpecs/versions", - "apiVersion": "2022-02-01", - "name": "[concat(variables('huntingQueryTemplateSpecName7'),'/',variables('huntingQueryVersion7'))]", + "type": "Microsoft.OperationalInsights/workspaces/providers/contentTemplates", + "apiVersion": "2023-04-01-preview", + "name": "[variables('analyticRuleTemplateSpecName6')]", "location": "[parameters('workspace-location')]", - "tags": { - "hidden-sentinelWorkspaceId": "[variables('workspaceResourceId')]", - "hidden-sentinelContentType": "HuntingQuery" - }, "dependsOn": [ - "[resourceId('Microsoft.Resources/templateSpecs', variables('huntingQueryTemplateSpecName7'))]" + "[extensionResourceId(resourceId('Microsoft.OperationalInsights/workspaces', parameters('workspace')), 'Microsoft.SecurityInsights/contentPackages', variables('_solutionId'))]" ], "properties": { - "description": "AzureSentinelConnectors_AdministrativeOperations_HuntingQueries Hunting Query with template version 2.0.6", + "description": "Granting_Permissions_To_Account_detection_AnalyticalRules Analytics Rule with template version 3.0.0", "mainTemplate": { "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", - "contentVersion": "[variables('huntingQueryVersion7')]", + "contentVersion": "[variables('analyticRuleVersion6')]", "parameters": {}, "variables": {}, "resources": [ { - "type": "Microsoft.OperationalInsights/savedSearches", - "apiVersion": "2020-08-01", - "name": "Azure_Activity_Hunting_Query_7", + "type": "Microsoft.SecurityInsights/AlertRuleTemplates", + "name": "[variables('analyticRulecontentId6')]", + "apiVersion": "2022-04-01-preview", + "kind": "Scheduled", "location": "[parameters('workspace-location')]", "properties": { - "eTag": "*", - "displayName": "Microsoft Sentinel Connectors Administrative Operations", - "category": "Hunting Queries", - "query": "let opValues = dynamic([\"Microsoft.SecurityInsights/dataConnectors/write\", \"Microsoft.SecurityInsights/dataConnectors/delete\"]);\n// Microsoft Sentinel Data Connectors Update / Delete\nAzureActivity\n| where OperationNameValue in~ (opValues)\n| where ActivitySubstatusValue in~ (\"Created\", \"OK\")\n| sort by TimeGenerated desc\n| extend Name = tostring(split(Caller,'@',0)[0]), UPNSuffix = tostring(split(Caller,'@',1)[0])\n| extend Account_0_Name = Name\n| extend Account_0_UPNSuffix = UPNSuffix\n| extend IP_0_Address = CallerIpAddress\n", - "version": 2, - "tags": [ + "description": "Identifies IPs from which users grant access to other users on Azure resources and alerts when a previously unseen source IP address is used.", + "displayName": "Suspicious granting of permissions to an account", + "enabled": false, + "query": "let starttime = 14d;\nlet endtime = 1d;\n// The number of operations above which an IP address is considered an unusual source of role assignment operations\nlet alertOperationThreshold = 5;\nlet AzureBuiltInRole = externaldata(Role:string,RoleDescription:string,ID:string) [@\"https://raw.githubusercontent.com/Azure/Azure-Sentinel/master/Sample%20Data/Feeds/AzureBuiltInRole.csv\"] with (format=\"csv\", ignoreFirstRecord=True);\nlet createRoleAssignmentActivity = AzureActivity\n| where OperationNameValue =~ \"microsoft.authorization/roleassignments/write\";\nlet RoleAssignedActivity = createRoleAssignmentActivity \n| where TimeGenerated between (ago(starttime) .. ago(endtime))\n| summarize count() by CallerIpAddress, Caller, bin(TimeGenerated, 1d)\n| where count_ >= alertOperationThreshold\n// Returns all the records from the right side that don't have matches from the left.\n| join kind = rightanti ( \ncreateRoleAssignmentActivity\n| where TimeGenerated > ago(endtime)\n| extend parsed_property = tostring(parse_json(Properties).requestbody)\n| extend PrincipalId = case(parsed_property has_cs 'PrincipalId',parse_json(parsed_property).Properties.PrincipalId, parsed_property has_cs 'principalId',parse_json(parsed_property).properties.principalId,\"\")\n| extend PrincipalType = case(parsed_property has_cs 'PrincipalType',parse_json(parsed_property).Properties.PrincipalType, parsed_property has_cs 'principalType',parse_json(parsed_property).properties.principalType, \"\")\n| extend Scope = case(parsed_property has_cs 'Scope',parse_json(parsed_property).Properties.Scope, parsed_property has_cs 'scope',parse_json(parsed_property).properties.scope,\"\")\n| extend RoleAddedDetails = case(parsed_property has_cs 'RoleDefinitionId',parse_json(parsed_property).Properties.RoleDefinitionId,parsed_property has_cs 'roleDefinitionId',parse_json(parsed_property).properties.roleDefinitionId,\"\")\n| summarize StartTimeUtc = min(TimeGenerated), EndTimeUtc = max(TimeGenerated), ActivityTimeStamp = make_set(TimeGenerated), ActivityStatusValue = make_set(ActivityStatusValue), CorrelationId = make_set(CorrelationId), ActivityCountByCallerIPAddress = count() \nby ResourceId, CallerIpAddress, Caller, OperationNameValue, Resource, ResourceGroup, PrincipalId, PrincipalType, Scope, RoleAddedDetails\n) on CallerIpAddress, Caller\n| extend timestamp = StartTimeUtc, AccountCustomEntity = Caller, IPCustomEntity = CallerIpAddress;\nlet RoleAssignedActivitywithRoleDetails = RoleAssignedActivity\n| extend RoleAssignedID = tostring(split(RoleAddedDetails, \"/\")[-1])\n// Returns all matching records from left and right sides.\n| join kind = inner (AzureBuiltInRole \n) on $left.RoleAssignedID == $right.ID;\nlet CallerIPCountSummary = RoleAssignedActivitywithRoleDetails | summarize AssignmentCountbyCaller = count() by Caller, CallerIpAddress;\nlet RoleAssignedActivityWithCount = RoleAssignedActivitywithRoleDetails | join kind = inner (CallerIPCountSummary | project Caller, AssignmentCountbyCaller, CallerIpAddress) on Caller, CallerIpAddress;\nRoleAssignedActivityWithCount\n| summarize arg_max(StartTimeUtc, *) by PrincipalId, RoleAssignedID\n// \tReturns all the records from the left side and only matching records from the right side.\n| join kind = leftouter( IdentityInfo\n| summarize arg_max(TimeGenerated, *) by AccountObjectId\n) on $left.PrincipalId == $right.AccountObjectId\n// Check if assignment count is greater than the threshold.\n| where AssignmentCountbyCaller >= alertOperationThreshold\n| project ActivityTimeStamp, OperationNameValue, Caller, CallerIpAddress, PrincipalId, RoleAssignedID, RoleAddedDetails, Role, RoleDescription, AccountUPN, AccountCreationTime, GroupMembership, UserType, ActivityStatusValue, ResourceGroup, PrincipalType, Scope, CorrelationId, timestamp, AccountCustomEntity, IPCustomEntity, AssignmentCountbyCaller\n| extend Name = tostring(split(Caller,'@',0)[0]), UPNSuffix = tostring(split(Caller,'@',1)[0])\n", + "queryFrequency": "P1D", + "queryPeriod": "P14D", + "severity": "Medium", + "suppressionDuration": "PT1H", + "suppressionEnabled": false, + "triggerOperator": "GreaterThan", + "triggerThreshold": 0, + "status": "Available", + "requiredDataConnectors": [ { - "name": "description", - "value": "Identifies a set of Microsoft Sentinel Data Connectors for administrative and operational detection queries for hunting activities." + "connectorId": "AzureActivity", + "dataTypes": [ + "AzureActivity" + ] }, { - "name": "tactics", - "value": "Impact" + "connectorId": "BehaviorAnalytics", + "dataTypes": [ + "IdentityInfo" + ] + } + ], + "tactics": [ + "Persistence", + "PrivilegeEscalation" + ], + "techniques": [ + "T1098", + "T1548" + ], + "entityMappings": [ + { + "fieldMappings": [ + { + "identifier": "Name", + "columnName": "Name" + }, + { + "identifier": "UPNSuffix", + "columnName": "UPNSuffix" + } + ], + "entityType": "Account" }, { - "name": "techniques", - "value": "T1496" + "fieldMappings": [ + { + "identifier": "Address", + "columnName": "CallerIpAddress" + } + ], + "entityType": "IP" } ] } @@ -972,13 +1152,13 @@ { "type": "Microsoft.OperationalInsights/workspaces/providers/metadata", "apiVersion": "2022-01-01-preview", - "name": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/',concat('HuntingQuery-', last(split(variables('huntingQueryId7'),'/'))))]", + "name": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/',concat('AnalyticsRule-', last(split(variables('analyticRuleId6'),'/'))))]", "properties": { - "description": "Azure Activity Hunting Query 7", - "parentId": "[variables('huntingQueryId7')]", - "contentId": "[variables('_huntingQuerycontentId7')]", - "kind": "HuntingQuery", - "version": "[variables('huntingQueryVersion7')]", + "description": "Azure Activity Analytics Rule 6", + "parentId": "[variables('analyticRuleId6')]", + "contentId": "[variables('_analyticRulecontentId6')]", + "kind": "AnalyticsRule", + "version": "[variables('analyticRuleVersion6')]", "source": { "kind": "Solution", "name": "Azure Activity", @@ -997,66 +1177,87 @@ } } ] - } - } - }, - { - "type": "Microsoft.Resources/templateSpecs", - "apiVersion": "2022-02-01", - "name": "[variables('huntingQueryTemplateSpecName8')]", - "location": "[parameters('workspace-location')]", - "tags": { - "hidden-sentinelWorkspaceId": "[variables('workspaceResourceId')]", - "hidden-sentinelContentType": "HuntingQuery" - }, - "properties": { - "description": "Azure Activity Hunting Query 8 with template", - "displayName": "Azure Activity Hunting Query template" + }, + "packageKind": "Solution", + "packageVersion": "[variables('_solutionVersion')]", + "packageName": "[variables('_solutionName')]", + "packageId": "[variables('_solutionId')]", + "contentSchemaVersion": "3.0.0", + "contentId": "[variables('_analyticRulecontentId6')]", + "contentKind": "AnalyticsRule", + "displayName": "Suspicious granting of permissions to an account", + "contentProductId": "[variables('_analyticRulecontentProductId6')]", + "id": "[variables('_analyticRulecontentProductId6')]", + "version": "[variables('analyticRuleVersion6')]" } }, { - "type": "Microsoft.Resources/templateSpecs/versions", - "apiVersion": "2022-02-01", - "name": "[concat(variables('huntingQueryTemplateSpecName8'),'/',variables('huntingQueryVersion8'))]", + "type": "Microsoft.OperationalInsights/workspaces/providers/contentTemplates", + "apiVersion": "2023-04-01-preview", + "name": "[variables('analyticRuleTemplateSpecName7')]", "location": "[parameters('workspace-location')]", - "tags": { - "hidden-sentinelWorkspaceId": "[variables('workspaceResourceId')]", - "hidden-sentinelContentType": "HuntingQuery" - }, "dependsOn": [ - "[resourceId('Microsoft.Resources/templateSpecs', variables('huntingQueryTemplateSpecName8'))]" + "[extensionResourceId(resourceId('Microsoft.OperationalInsights/workspaces', parameters('workspace')), 'Microsoft.SecurityInsights/contentPackages', variables('_solutionId'))]" ], "properties": { - "description": "AzureSentinelWorkbooks_AdministrativeOperation_HuntingQueries Hunting Query with template version 2.0.6", + "description": "NRT-AADHybridHealthADFSNewServer_AnalyticalRules Analytics Rule with template version 3.0.0", "mainTemplate": { "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", - "contentVersion": "[variables('huntingQueryVersion8')]", + "contentVersion": "[variables('analyticRuleVersion7')]", "parameters": {}, "variables": {}, "resources": [ { - "type": "Microsoft.OperationalInsights/savedSearches", - "apiVersion": "2020-08-01", - "name": "Azure_Activity_Hunting_Query_8", + "type": "Microsoft.SecurityInsights/AlertRuleTemplates", + "name": "[variables('analyticRulecontentId7')]", + "apiVersion": "2022-04-01-preview", + "kind": "NRT", "location": "[parameters('workspace-location')]", "properties": { - "eTag": "*", - "displayName": "Microsoft Sentinel Workbooks Administrative Operations", - "category": "Hunting Queries", - "query": "let opValues = dynamic([\"microsoft.insights/workbooks/write\", \"microsoft.insights/workbooks/delete\"]);\n// Microsoft Sentinel Workbook Create / Update / Delete\nAzureActivity\n| where Category =~ \"Administrative\"\n| where OperationNameValue in~ (opValues)\n| where ActivitySubstatusValue in~ (\"Created\", \"OK\")\n| sort by TimeGenerated desc\n| extend Name = tostring(split(Caller,'@',0)[0]), UPNSuffix = tostring(split(Caller,'@',1)[0])\n| extend Account_0_Name = Name\n| extend Account_0_UPNSuffix = UPNSuffix\n| extend IP_0_Address = CallerIpAddress\n", - "version": 2, - "tags": [ + "description": "This detection uses AzureActivity logs (Administrative category) to identify the creation or update of a server instance in an Azure AD Hybrid Health AD FS service.\nA threat actor can create a new AD Health ADFS service and create a fake server instance to spoof AD FS signing logs. There is no need to compromise an on-premises AD FS server.\nThis can be done programmatically via HTTP requests to Azure. More information in this blog: https://o365blog.com/post/hybridhealthagent/", + "displayName": "NRT Azure Active Directory Hybrid Health AD FS New Server", + "enabled": false, + "query": "AzureActivity\n| where CategoryValue =~ 'Administrative'\n| where ResourceProviderValue =~ 'Microsoft.ADHybridHealthService'\n| where _ResourceId has 'AdFederationService'\n| where OperationNameValue =~ 'Microsoft.ADHybridHealthService/services/servicemembers/action'\n| extend claimsJson = parse_json(Claims)\n| extend AppId = tostring(claimsJson.appid), AccountName = tostring(claimsJson.name), Name = tostring(split(Caller,'@',0)[0]), UPNSuffix = tostring(split(Caller,'@',1)[0])\n| project-away claimsJson\n", + "severity": "Medium", + "suppressionDuration": "PT1H", + "suppressionEnabled": false, + "status": "Available", + "requiredDataConnectors": [ { - "name": "description", - "value": "Identifies set of Microsoft Sentinel Workbooks administrative operational detection queries for hunting activites" - }, + "connectorId": "AzureActivity", + "dataTypes": [ + "AzureActivity" + ] + } + ], + "tactics": [ + "DefenseEvasion" + ], + "techniques": [ + "T1578" + ], + "entityMappings": [ { - "name": "tactics", - "value": "Impact" + "fieldMappings": [ + { + "identifier": "Name", + "columnName": "Name" + }, + { + "identifier": "UPNSuffix", + "columnName": "UPNSuffix" + } + ], + "entityType": "Account" }, { - "name": "techniques", - "value": "T1496" + "fieldMappings": [ + { + "identifier": "Address", + "columnName": "CallerIpAddress" + } + ], + "entityType": "IP" } ] } @@ -1064,13 +1265,13 @@ { "type": "Microsoft.OperationalInsights/workspaces/providers/metadata", "apiVersion": "2022-01-01-preview", - "name": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/',concat('HuntingQuery-', last(split(variables('huntingQueryId8'),'/'))))]", + "name": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/',concat('AnalyticsRule-', last(split(variables('analyticRuleId7'),'/'))))]", "properties": { - "description": "Azure Activity Hunting Query 8", - "parentId": "[variables('huntingQueryId8')]", - "contentId": "[variables('_huntingQuerycontentId8')]", - "kind": "HuntingQuery", - "version": "[variables('huntingQueryVersion8')]", + "description": "Azure Activity Analytics Rule 7", + "parentId": "[variables('analyticRuleId7')]", + "contentId": "[variables('_analyticRulecontentId7')]", + "kind": "AnalyticsRule", + "version": "[variables('analyticRuleVersion7')]", "source": { "kind": "Solution", "name": "Azure Activity", @@ -1089,66 +1290,96 @@ } } ] - } - } - }, - { - "type": "Microsoft.Resources/templateSpecs", - "apiVersion": "2022-02-01", - "name": "[variables('huntingQueryTemplateSpecName9')]", - "location": "[parameters('workspace-location')]", - "tags": { - "hidden-sentinelWorkspaceId": "[variables('workspaceResourceId')]", - "hidden-sentinelContentType": "HuntingQuery" - }, - "properties": { - "description": "Azure Activity Hunting Query 9 with template", - "displayName": "Azure Activity Hunting Query template" + }, + "packageKind": "Solution", + "packageVersion": "[variables('_solutionVersion')]", + "packageName": "[variables('_solutionName')]", + "packageId": "[variables('_solutionId')]", + "contentSchemaVersion": "3.0.0", + "contentId": "[variables('_analyticRulecontentId7')]", + "contentKind": "AnalyticsRule", + "displayName": "NRT Azure Active Directory Hybrid Health AD FS New Server", + "contentProductId": "[variables('_analyticRulecontentProductId7')]", + "id": "[variables('_analyticRulecontentProductId7')]", + "version": "[variables('analyticRuleVersion7')]" } }, { - "type": "Microsoft.Resources/templateSpecs/versions", - "apiVersion": "2022-02-01", - "name": "[concat(variables('huntingQueryTemplateSpecName9'),'/',variables('huntingQueryVersion9'))]", + "type": "Microsoft.OperationalInsights/workspaces/providers/contentTemplates", + "apiVersion": "2023-04-01-preview", + "name": "[variables('analyticRuleTemplateSpecName8')]", "location": "[parameters('workspace-location')]", - "tags": { - "hidden-sentinelWorkspaceId": "[variables('workspaceResourceId')]", - "hidden-sentinelContentType": "HuntingQuery" - }, "dependsOn": [ - "[resourceId('Microsoft.Resources/templateSpecs', variables('huntingQueryTemplateSpecName9'))]" + "[extensionResourceId(resourceId('Microsoft.OperationalInsights/workspaces', parameters('workspace')), 'Microsoft.SecurityInsights/contentPackages', variables('_solutionId'))]" ], "properties": { - "description": "AzureVirtualNetworkSubnets_AdministrativeOperationset_HuntingQueries Hunting Query with template version 2.0.6", + "description": "NRT_Creation_of_Expensive_Computes_in_Azure_AnalyticalRules Analytics Rule with template version 3.0.0", "mainTemplate": { "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", - "contentVersion": "[variables('huntingQueryVersion9')]", + "contentVersion": "[variables('analyticRuleVersion8')]", "parameters": {}, "variables": {}, "resources": [ { - "type": "Microsoft.OperationalInsights/savedSearches", - "apiVersion": "2020-08-01", - "name": "Azure_Activity_Hunting_Query_9", + "type": "Microsoft.SecurityInsights/AlertRuleTemplates", + "name": "[variables('analyticRulecontentId8')]", + "apiVersion": "2022-04-01-preview", + "kind": "NRT", "location": "[parameters('workspace-location')]", "properties": { - "eTag": "*", - "displayName": "Azure Virtual Network Subnets Administrative Operations", - "category": "Hunting Queries", - "query": "let opValues = dynamic([\"Microsoft.Network/virtualNetworks/subnets/write\",\"Microsoft.Network/virtualNetworks/subnets/delete\"]);\n// Creating, Updating or Deleting Virtual Network Subnets\nAzureActivity\n| where CategoryValue =~ \"Administrative\"\n| where OperationNameValue in~ (opValues)\n| where ActivitySubstatusValue in~ (\"Created\",\"Accepted\")\n| sort by TimeGenerated desc\n| extend Name = tostring(split(Caller,'@',0)[0]), UPNSuffix = tostring(split(Caller,'@',1)[0])\n| extend Account_0_Name = Name\n| extend Account_0_UPNSuffix = UPNSuffix\n| extend IP_0_Address = CallerIpAddress\n", - "version": 2, - "tags": [ - { - "name": "description", - "value": "Identifies a set of Azure Virtual Network Subnets for administrative and operational detection queries for hunting activities." - }, + "description": "Identifies the creation of large size or expensive VMs (with GPUs or with a large number of virtual CPUs) in Azure.\nAn adversary may create new or update existing virtual machines to evade defenses or use them for cryptomining purposes.\nFor Windows/Linux Vm Sizes, see https://docs.microsoft.com/azure/virtual-machines/windows/sizes \nAzure VM Naming Conventions, see https://docs.microsoft.com/azure/virtual-machines/vm-naming-conventions", + "displayName": "NRT Creation of expensive computes in Azure", + "enabled": false, + "query": "let tokens = dynamic([\"416\",\"208\",\"192\",\"128\",\"120\",\"96\",\"80\",\"72\",\"64\",\"48\",\"44\",\"40\",\"nc12\",\"nc24\",\"nv24\"]);\nlet operationList = dynamic([\"microsoft.compute/virtualmachines/write\", \"microsoft.resources/deployments/write\"]);\nAzureActivity\n| where OperationNameValue in~ (operationList)\n| where ActivityStatusValue startswith \"Accept\"\n| where Properties has 'vmSize'\n| extend parsed_property= parse_json(tostring((parse_json(Properties).responseBody))).properties\n| extend vmSize = tostring((parsed_property.hardwareProfile).vmSize)\n| mv-apply token=tokens to typeof(string) on (where vmSize contains token)\n| extend ComputerName = tostring((parsed_property.osProfile).computerName)\n| project TimeGenerated, OperationNameValue, ActivityStatusValue, Caller, CallerIpAddress, ComputerName, vmSize\n| extend Name = tostring(split(Caller,'@',0)[0]), UPNSuffix = tostring(split(Caller,'@',1)[0])\n", + "severity": "Medium", + "suppressionDuration": "PT1H", + "suppressionEnabled": false, + "status": "Available", + "requiredDataConnectors": [ { - "name": "tactics", - "value": "Impact" + "connectorId": "AzureActivity", + "dataTypes": [ + "AzureActivity" + ] + } + ], + "tactics": [ + "DefenseEvasion" + ], + "techniques": [ + "T1578" + ], + "entityMappings": [ + { + "fieldMappings": [ + { + "identifier": "Name", + "columnName": "Name" + }, + { + "identifier": "UPNSuffix", + "columnName": "UPNSuffix" + } + ], + "entityType": "Account" }, { - "name": "techniques", - "value": "T1496" + "fieldMappings": [ + { + "identifier": "HostName", + "columnName": "ComputerName" + } + ], + "entityType": "Host" + }, + { + "fieldMappings": [ + { + "identifier": "Address", + "columnName": "CallerIpAddress" + } + ], + "entityType": "IP" } ] } @@ -1156,13 +1387,13 @@ { "type": "Microsoft.OperationalInsights/workspaces/providers/metadata", "apiVersion": "2022-01-01-preview", - "name": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/',concat('HuntingQuery-', last(split(variables('huntingQueryId9'),'/'))))]", + "name": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/',concat('AnalyticsRule-', last(split(variables('analyticRuleId8'),'/'))))]", "properties": { - "description": "Azure Activity Hunting Query 9", - "parentId": "[variables('huntingQueryId9')]", - "contentId": "[variables('_huntingQuerycontentId9')]", - "kind": "HuntingQuery", - "version": "[variables('huntingQueryVersion9')]", + "description": "Azure Activity Analytics Rule 8", + "parentId": "[variables('analyticRuleId8')]", + "contentId": "[variables('_analyticRulecontentId8')]", + "kind": "AnalyticsRule", + "version": "[variables('analyticRuleVersion8')]", "source": { "kind": "Solution", "name": "Azure Activity", @@ -1181,66 +1412,91 @@ } } ] - } - } - }, - { - "type": "Microsoft.Resources/templateSpecs", - "apiVersion": "2022-02-01", - "name": "[variables('huntingQueryTemplateSpecName10')]", - "location": "[parameters('workspace-location')]", - "tags": { - "hidden-sentinelWorkspaceId": "[variables('workspaceResourceId')]", - "hidden-sentinelContentType": "HuntingQuery" - }, - "properties": { - "description": "Azure Activity Hunting Query 10 with template", - "displayName": "Azure Activity Hunting Query template" + }, + "packageKind": "Solution", + "packageVersion": "[variables('_solutionVersion')]", + "packageName": "[variables('_solutionName')]", + "packageId": "[variables('_solutionId')]", + "contentSchemaVersion": "3.0.0", + "contentId": "[variables('_analyticRulecontentId8')]", + "contentKind": "AnalyticsRule", + "displayName": "NRT Creation of expensive computes in Azure", + "contentProductId": "[variables('_analyticRulecontentProductId8')]", + "id": "[variables('_analyticRulecontentProductId8')]", + "version": "[variables('analyticRuleVersion8')]" } }, { - "type": "Microsoft.Resources/templateSpecs/versions", - "apiVersion": "2022-02-01", - "name": "[concat(variables('huntingQueryTemplateSpecName10'),'/',variables('huntingQueryVersion10'))]", + "type": "Microsoft.OperationalInsights/workspaces/providers/contentTemplates", + "apiVersion": "2023-04-01-preview", + "name": "[variables('analyticRuleTemplateSpecName9')]", "location": "[parameters('workspace-location')]", - "tags": { - "hidden-sentinelWorkspaceId": "[variables('workspaceResourceId')]", - "hidden-sentinelContentType": "HuntingQuery" - }, "dependsOn": [ - "[resourceId('Microsoft.Resources/templateSpecs', variables('huntingQueryTemplateSpecName10'))]" + "[extensionResourceId(resourceId('Microsoft.OperationalInsights/workspaces', parameters('workspace')), 'Microsoft.SecurityInsights/contentPackages', variables('_solutionId'))]" ], "properties": { - "description": "Common_Deployed_Resources_HuntingQueries Hunting Query with template version 2.0.6", + "description": "New-CloudShell-User_AnalyticalRules Analytics Rule with template version 3.0.0", "mainTemplate": { "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", - "contentVersion": "[variables('huntingQueryVersion10')]", + "contentVersion": "[variables('analyticRuleVersion9')]", "parameters": {}, "variables": {}, "resources": [ { - "type": "Microsoft.OperationalInsights/savedSearches", - "apiVersion": "2020-08-01", - "name": "Azure_Activity_Hunting_Query_10", + "type": "Microsoft.SecurityInsights/AlertRuleTemplates", + "name": "[variables('analyticRulecontentId9')]", + "apiVersion": "2022-04-01-preview", + "kind": "Scheduled", "location": "[parameters('workspace-location')]", "properties": { - "eTag": "*", - "displayName": "Common deployed resources", - "category": "Hunting Queries", - "query": "AzureActivity\n| where OperationNameValue has_any (@\"deployments/write\", @\"virtualMachines/write\") \n| where ActivityStatusValue =~ \"Succeeded\"\n| summarize by bin(TimeGenerated,1d), Resource, ResourceGroup, ResourceId, OperationNameValue, Caller\n| evaluate basket()\n| where isnotempty(Caller) and isnotempty(Resource) and isnotempty(TimeGenerated)\n| order by Percent desc, TimeGenerated desc\n| extend Name = tostring(split(Caller,'@',0)[0]), UPNSuffix = tostring(split(Caller,'@',1)[0])\n| extend Account_0_Name = Name\n| extend Account_0_UPNSuffix = UPNSuffix\n| extend AzureResource_0_ResourceId = ResourceId\n// remove comments below on filters if the goal is to see more common or more rare Resource, Resource Group and Caller combinations\n//| where Percent <= 40 // <-- more rare\n//| where Percent >= 60 // <-- more common\n", - "version": 2, - "tags": [ + "description": "Identifies when a user creates an Azure CloudShell for the first time.\nMonitor this activity to ensure only the expected users are using CloudShell.", + "displayName": "New CloudShell User", + "enabled": false, + "query": "let match_window = 3m;\nAzureActivity\n| where ResourceGroup has \"cloud-shell\"\n| where (OperationNameValue =~ \"Microsoft.Storage/storageAccounts/listKeys/action\")\n| where ActivityStatusValue =~ \"Success\"\n| extend TimeKey = bin(TimeGenerated, match_window), AzureIP = CallerIpAddress\n| join kind = inner\n(AzureActivity\n| where ResourceGroup has \"cloud-shell\"\n| where (OperationNameValue =~ \"Microsoft.Storage/storageAccounts/write\")\n| extend TimeKey = bin(TimeGenerated, match_window), UserIP = CallerIpAddress\n) on Caller, TimeKey\n| summarize count() by TimeKey, Caller, ResourceGroup, SubscriptionId, TenantId, AzureIP, UserIP, HTTPRequest, Type, Properties, CategoryValue, OperationList = strcat(OperationNameValue, ' , ', OperationNameValue1)\n| extend Name = tostring(split(Caller,'@',0)[0]), UPNSuffix = tostring(split(Caller,'@',1)[0])\n", + "queryFrequency": "P1D", + "queryPeriod": "P1D", + "severity": "Low", + "suppressionDuration": "PT1H", + "suppressionEnabled": false, + "triggerOperator": "GreaterThan", + "triggerThreshold": 0, + "status": "Available", + "requiredDataConnectors": [ { - "name": "description", - "value": "This query looks for common deployed resources (resource name and resource groups) and can be used\nin combination with other signals that show suspicious deployment to evaluate if the resource is one\nthat is commonly being deployed/created or unique.\nTo understand the basket() function better see - https://docs.microsoft.com/azure/data-explorer/kusto/query/basketplugin" - }, + "connectorId": "AzureActivity", + "dataTypes": [ + "AzureActivity" + ] + } + ], + "tactics": [ + "Execution" + ], + "techniques": [ + "T1059" + ], + "entityMappings": [ { - "name": "tactics", - "value": "Impact" + "fieldMappings": [ + { + "identifier": "Name", + "columnName": "Name" + }, + { + "identifier": "UPNSuffix", + "columnName": "UPNSuffix" + } + ], + "entityType": "Account" }, { - "name": "techniques", - "value": "T1496" + "fieldMappings": [ + { + "identifier": "Address", + "columnName": "UserIP" + } + ], + "entityType": "IP" } ] } @@ -1248,13 +1504,13 @@ { "type": "Microsoft.OperationalInsights/workspaces/providers/metadata", "apiVersion": "2022-01-01-preview", - "name": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/',concat('HuntingQuery-', last(split(variables('huntingQueryId10'),'/'))))]", + "name": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/',concat('AnalyticsRule-', last(split(variables('analyticRuleId9'),'/'))))]", "properties": { - "description": "Azure Activity Hunting Query 10", - "parentId": "[variables('huntingQueryId10')]", - "contentId": "[variables('_huntingQuerycontentId10')]", - "kind": "HuntingQuery", - "version": "[variables('huntingQueryVersion10')]", + "description": "Azure Activity Analytics Rule 9", + "parentId": "[variables('analyticRuleId9')]", + "contentId": "[variables('_analyticRulecontentId9')]", + "kind": "AnalyticsRule", + "version": "[variables('analyticRuleVersion9')]", "source": { "kind": "Solution", "name": "Azure Activity", @@ -1273,66 +1529,95 @@ } } ] - } - } - }, - { - "type": "Microsoft.Resources/templateSpecs", - "apiVersion": "2022-02-01", - "name": "[variables('huntingQueryTemplateSpecName11')]", - "location": "[parameters('workspace-location')]", - "tags": { - "hidden-sentinelWorkspaceId": "[variables('workspaceResourceId')]", - "hidden-sentinelContentType": "HuntingQuery" - }, - "properties": { - "description": "Azure Activity Hunting Query 11 with template", - "displayName": "Azure Activity Hunting Query template" + }, + "packageKind": "Solution", + "packageVersion": "[variables('_solutionVersion')]", + "packageName": "[variables('_solutionName')]", + "packageId": "[variables('_solutionId')]", + "contentSchemaVersion": "3.0.0", + "contentId": "[variables('_analyticRulecontentId9')]", + "contentKind": "AnalyticsRule", + "displayName": "New CloudShell User", + "contentProductId": "[variables('_analyticRulecontentProductId9')]", + "id": "[variables('_analyticRulecontentProductId9')]", + "version": "[variables('analyticRuleVersion9')]" } }, { - "type": "Microsoft.Resources/templateSpecs/versions", - "apiVersion": "2022-02-01", - "name": "[concat(variables('huntingQueryTemplateSpecName11'),'/',variables('huntingQueryVersion11'))]", + "type": "Microsoft.OperationalInsights/workspaces/providers/contentTemplates", + "apiVersion": "2023-04-01-preview", + "name": "[variables('analyticRuleTemplateSpecName10')]", "location": "[parameters('workspace-location')]", - "tags": { - "hidden-sentinelWorkspaceId": "[variables('workspaceResourceId')]", - "hidden-sentinelContentType": "HuntingQuery" - }, "dependsOn": [ - "[resourceId('Microsoft.Resources/templateSpecs', variables('huntingQueryTemplateSpecName11'))]" + "[extensionResourceId(resourceId('Microsoft.OperationalInsights/workspaces', parameters('workspace')), 'Microsoft.SecurityInsights/contentPackages', variables('_solutionId'))]" ], "properties": { - "description": "Creating_Anomalous_Number_Of_Resources_HuntingQueries Hunting Query with template version 2.0.6", + "description": "NewResourceGroupsDeployedTo_AnalyticalRules Analytics Rule with template version 3.0.0", "mainTemplate": { "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", - "contentVersion": "[variables('huntingQueryVersion11')]", + "contentVersion": "[variables('analyticRuleVersion10')]", "parameters": {}, "variables": {}, "resources": [ { - "type": "Microsoft.OperationalInsights/savedSearches", - "apiVersion": "2020-08-01", - "name": "Azure_Activity_Hunting_Query_11", + "type": "Microsoft.SecurityInsights/AlertRuleTemplates", + "name": "[variables('analyticRulecontentId10')]", + "apiVersion": "2022-04-01-preview", + "kind": "Scheduled", "location": "[parameters('workspace-location')]", "properties": { - "eTag": "*", - "displayName": "Creation of an anomalous number of resources", - "category": "Hunting Queries", - "query": "AzureActivity\n| where OperationNameValue in~ (\"microsoft.compute/virtualMachines/write\", \"microsoft.resources/deployments/write\")\n| where ActivityStatusValue == \"Succeeded\" \n| make-series dcount(ResourceId) default=0 on EventSubmissionTimestamp in range(ago(7d), now(), 1d) by Caller\n| extend Name = tostring(split(Caller,'@',0)[0]), UPNSuffix = tostring(split(Caller,'@',1)[0])\n| extend Account_0_Name = Name\n| extend Account_0_UPNSuffix = UPNSuffix\n", - "version": 2, - "tags": [ + "description": "Identifies when a rare Resource and ResourceGroup deployment occurs by a previously unseen caller.", + "displayName": "Suspicious Resource deployment", + "enabled": false, + "query": "// Add or remove operation names below as per your requirements. For operations lists, please refer to https://learn.microsoft.com/en-us/Azure/role-based-access-control/resource-provider-operations#all\nlet szOperationNames = dynamic([\"Microsoft.Compute/virtualMachines/write\", \"Microsoft.Resources/deployments/write\", \"Microsoft.Resources/subscriptions/resourceGroups/write\"]);\nlet starttime = 14d;\nlet endtime = 1d;\nlet RareCaller = AzureActivity\n| where TimeGenerated between (ago(starttime) .. ago(endtime))\n| where OperationNameValue in~ (szOperationNames)\n| summarize count() by CallerIpAddress, Caller, OperationNameValue, bin(TimeGenerated,1d)\n// Returns all the records from the right side that don't have matches from the left.\n| join kind=rightantisemi (\nAzureActivity\n| where TimeGenerated > ago(endtime)\n| where OperationNameValue in~ (szOperationNames)\n| summarize StartTimeUtc = min(TimeGenerated), EndTimeUtc = max(TimeGenerated), ActivityTimeStamp = make_set(TimeGenerated,100), ActivityStatusValue = make_set(ActivityStatusValue,100), CorrelationIds = make_set(CorrelationId,100), ResourceGroups = make_set(ResourceGroup,100), ResourceIds = make_set(_ResourceId,100), ActivityCountByCallerIPAddress = count()\nby CallerIpAddress, Caller, OperationNameValue) on CallerIpAddress, Caller, OperationNameValue;\nRareCaller\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 '@',Caller,\"\")\n", + "queryFrequency": "P1D", + "queryPeriod": "P14D", + "severity": "Low", + "suppressionDuration": "PT1H", + "suppressionEnabled": false, + "triggerOperator": "GreaterThan", + "triggerThreshold": 0, + "status": "Available", + "requiredDataConnectors": [ { - "name": "description", - "value": "Looks for anomalous number of resources creation or deployment activities in azure activity log.\nIt is best to run this query on a look back period which is at least 7 days." - }, + "connectorId": "AzureActivity", + "dataTypes": [ + "AzureActivity" + ] + } + ], + "tactics": [ + "Impact" + ], + "techniques": [ + "T1496" + ], + "entityMappings": [ { - "name": "tactics", - "value": "Impact" + "fieldMappings": [ + { + "identifier": "Name", + "columnName": "Name" + }, + { + "identifier": "UPNSuffix", + "columnName": "UPNSuffix" + }, + { + "identifier": "AadUserId", + "columnName": "AadUserId" + } + ], + "entityType": "Account" }, { - "name": "techniques", - "value": "T1496" + "fieldMappings": [ + { + "identifier": "Address", + "columnName": "CallerIpAddress" + } + ], + "entityType": "IP" } ] } @@ -1340,13 +1625,13 @@ { "type": "Microsoft.OperationalInsights/workspaces/providers/metadata", "apiVersion": "2022-01-01-preview", - "name": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/',concat('HuntingQuery-', last(split(variables('huntingQueryId11'),'/'))))]", + "name": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/',concat('AnalyticsRule-', last(split(variables('analyticRuleId10'),'/'))))]", "properties": { - "description": "Azure Activity Hunting Query 11", - "parentId": "[variables('huntingQueryId11')]", - "contentId": "[variables('_huntingQuerycontentId11')]", - "kind": "HuntingQuery", - "version": "[variables('huntingQueryVersion11')]", + "description": "Azure Activity Analytics Rule 10", + "parentId": "[variables('analyticRuleId10')]", + "contentId": "[variables('_analyticRulecontentId10')]", + "kind": "AnalyticsRule", + "version": "[variables('analyticRuleVersion10')]", "source": { "kind": "Solution", "name": "Azure Activity", @@ -1365,80 +1650,107 @@ } } ] - } - } - }, - { - "type": "Microsoft.Resources/templateSpecs", - "apiVersion": "2022-02-01", - "name": "[variables('huntingQueryTemplateSpecName12')]", - "location": "[parameters('workspace-location')]", - "tags": { - "hidden-sentinelWorkspaceId": "[variables('workspaceResourceId')]", - "hidden-sentinelContentType": "HuntingQuery" - }, - "properties": { - "description": "Azure Activity Hunting Query 12 with template", - "displayName": "Azure Activity Hunting Query template" + }, + "packageKind": "Solution", + "packageVersion": "[variables('_solutionVersion')]", + "packageName": "[variables('_solutionName')]", + "packageId": "[variables('_solutionId')]", + "contentSchemaVersion": "3.0.0", + "contentId": "[variables('_analyticRulecontentId10')]", + "contentKind": "AnalyticsRule", + "displayName": "Suspicious Resource deployment", + "contentProductId": "[variables('_analyticRulecontentProductId10')]", + "id": "[variables('_analyticRulecontentProductId10')]", + "version": "[variables('analyticRuleVersion10')]" } }, { - "type": "Microsoft.Resources/templateSpecs/versions", - "apiVersion": "2022-02-01", - "name": "[concat(variables('huntingQueryTemplateSpecName12'),'/',variables('huntingQueryVersion12'))]", + "type": "Microsoft.OperationalInsights/workspaces/providers/contentTemplates", + "apiVersion": "2023-04-01-preview", + "name": "[variables('analyticRuleTemplateSpecName11')]", "location": "[parameters('workspace-location')]", - "tags": { - "hidden-sentinelWorkspaceId": "[variables('workspaceResourceId')]", - "hidden-sentinelContentType": "HuntingQuery" - }, "dependsOn": [ - "[resourceId('Microsoft.Resources/templateSpecs', variables('huntingQueryTemplateSpecName12'))]" + "[extensionResourceId(resourceId('Microsoft.OperationalInsights/workspaces', parameters('workspace')), 'Microsoft.SecurityInsights/contentPackages', variables('_solutionId'))]" ], "properties": { - "description": "Granting_Permissions_to_Account_HuntingQueries Hunting Query with template version 2.0.6", + "description": "RareOperations_AnalyticalRules Analytics Rule with template version 3.0.0", "mainTemplate": { "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", - "contentVersion": "[variables('huntingQueryVersion12')]", + "contentVersion": "[variables('analyticRuleVersion11')]", "parameters": {}, "variables": {}, "resources": [ { - "type": "Microsoft.OperationalInsights/savedSearches", - "apiVersion": "2020-08-01", - "name": "Azure_Activity_Hunting_Query_12", + "type": "Microsoft.SecurityInsights/AlertRuleTemplates", + "name": "[variables('analyticRulecontentId11')]", + "apiVersion": "2022-04-01-preview", + "kind": "Scheduled", "location": "[parameters('workspace-location')]", "properties": { - "eTag": "*", - "displayName": "Granting permissions to account", - "category": "Hunting Queries", - "query": "AzureActivity\n| where OperationName =~ \"Create role assignment\"\n| where ActivityStatus =~ \"Succeeded\" \n| project Caller, CallerIpAddress\n| evaluate basket()\n// Returns all the records from the left side and only matching records from the right side.\n| join kind=leftouter (AzureActivity\n| where OperationName =~ \"Create role assignment\"\n| where ActivityStatus =~ \"Succeeded\"\n| summarize StartTime = min(TimeGenerated), EndTime = max(TimeGenerated) by Caller, CallerIpAddress)\non Caller, CallerIpAddress\n| project-away Caller1, CallerIpAddress1\n| where isnotempty(StartTime)\n| extend Name = tostring(split(Caller,'@',0)[0]), UPNSuffix = tostring(split(Caller,'@',1)[0])\n| extend Account_0_Name = Name\n| extend Account_0_UPNSuffix = UPNSuffix\n| extend IP_0_Address = CallerIpAddress\n", - "version": 2, - "tags": [ - { - "name": "description", - "value": "Shows the most prevalent users who grant access to others on Azure resources. List the common source IP address for each of those accounts. If an operation is not from those IP addresses, it may be worthy of investigation." - }, - { - "name": "tactics", - "value": "Persistence,PrivilegeEscalation" - }, + "description": "This query looks for a few sensitive subscription-level events based on Azure Activity Logs. For example, this monitors for the operation name 'Create or Update Snapshot', which is used for creating backups but could be misused by attackers to dump hashes or extract sensitive information from the disk.", + "displayName": "Rare subscription-level operations in Azure", + "enabled": false, + "query": "let starttime = 14d;\nlet endtime = 1d;\n// The number of operations above which an IP address is considered an unusual source of role assignment operations\nlet alertOperationThreshold = 5;\n// Add or remove operation names below as per your requirements. For operations lists, please refer to https://learn.microsoft.com/en-us/Azure/role-based-access-control/resource-provider-operations#all\nlet SensitiveOperationList = dynamic([\"microsoft.compute/snapshots/write\", \"microsoft.network/networksecuritygroups/write\", \"microsoft.storage/storageaccounts/listkeys/action\"]);\nlet SensitiveActivity = AzureActivity\n| where OperationNameValue in~ (SensitiveOperationList) or OperationNameValue hassuffix \"listkeys/action\"\n| where ActivityStatusValue =~ \"Success\";\nSensitiveActivity\n| where TimeGenerated between (ago(starttime) .. ago(endtime))\n| summarize count() by CallerIpAddress, Caller, OperationNameValue, bin(TimeGenerated,1d)\n| where count_ >= alertOperationThreshold\n// Returns all the records from the right side that don't have matches from the left\n| join kind = rightanti (\nSensitiveActivity\n| where TimeGenerated >= ago(endtime)\n| summarize StartTimeUtc = min(TimeGenerated), EndTimeUtc = max(TimeGenerated), ActivityTimeStamp = make_list(TimeGenerated), ActivityStatusValue = make_list(ActivityStatusValue), CorrelationIds = make_list(CorrelationId), ResourceGroups = make_list(ResourceGroup), ResourceIds = make_list(_ResourceId), ActivityCountByCallerIPAddress = count()\nby CallerIpAddress, Caller, OperationNameValue\n| where ActivityCountByCallerIPAddress >= alertOperationThreshold\n) on CallerIpAddress, Caller, OperationNameValue\n| extend Name = tostring(split(Caller,'@',0)[0]), UPNSuffix = tostring(split(Caller,'@',1)[0])\n", + "queryFrequency": "P1D", + "queryPeriod": "P14D", + "severity": "Low", + "suppressionDuration": "PT1H", + "suppressionEnabled": false, + "triggerOperator": "GreaterThan", + "triggerThreshold": 0, + "status": "Available", + "requiredDataConnectors": [ { - "name": "techniques", - "value": "T1098" + "connectorId": "AzureActivity", + "dataTypes": [ + "AzureActivity" + ] } - ] - } - }, - { - "type": "Microsoft.OperationalInsights/workspaces/providers/metadata", + ], + "tactics": [ + "CredentialAccess", + "Persistence" + ], + "techniques": [ + "T1003", + "T1098" + ], + "entityMappings": [ + { + "fieldMappings": [ + { + "identifier": "Name", + "columnName": "Name" + }, + { + "identifier": "UPNSuffix", + "columnName": "UPNSuffix" + } + ], + "entityType": "Account" + }, + { + "fieldMappings": [ + { + "identifier": "Address", + "columnName": "CallerIpAddress" + } + ], + "entityType": "IP" + } + ] + } + }, + { + "type": "Microsoft.OperationalInsights/workspaces/providers/metadata", "apiVersion": "2022-01-01-preview", - "name": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/',concat('HuntingQuery-', last(split(variables('huntingQueryId12'),'/'))))]", + "name": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/',concat('AnalyticsRule-', last(split(variables('analyticRuleId11'),'/'))))]", "properties": { - "description": "Azure Activity Hunting Query 12", - "parentId": "[variables('huntingQueryId12')]", - "contentId": "[variables('_huntingQuerycontentId12')]", - "kind": "HuntingQuery", - "version": "[variables('huntingQueryVersion12')]", + "description": "Azure Activity Analytics Rule 11", + "parentId": "[variables('analyticRuleId11')]", + "contentId": "[variables('_analyticRulecontentId11')]", + "kind": "AnalyticsRule", + "version": "[variables('analyticRuleVersion11')]", "source": { "kind": "Solution", "name": "Azure Activity", @@ -1457,66 +1769,86 @@ } } ] - } - } - }, - { - "type": "Microsoft.Resources/templateSpecs", - "apiVersion": "2022-02-01", - "name": "[variables('huntingQueryTemplateSpecName13')]", - "location": "[parameters('workspace-location')]", - "tags": { - "hidden-sentinelWorkspaceId": "[variables('workspaceResourceId')]", - "hidden-sentinelContentType": "HuntingQuery" - }, - "properties": { - "description": "Azure Activity Hunting Query 13 with template", - "displayName": "Azure Activity Hunting Query template" + }, + "packageKind": "Solution", + "packageVersion": "[variables('_solutionVersion')]", + "packageName": "[variables('_solutionName')]", + "packageId": "[variables('_solutionId')]", + "contentSchemaVersion": "3.0.0", + "contentId": "[variables('_analyticRulecontentId11')]", + "contentKind": "AnalyticsRule", + "displayName": "Rare subscription-level operations in Azure", + "contentProductId": "[variables('_analyticRulecontentProductId11')]", + "id": "[variables('_analyticRulecontentProductId11')]", + "version": "[variables('analyticRuleVersion11')]" } }, { - "type": "Microsoft.Resources/templateSpecs/versions", - "apiVersion": "2022-02-01", - "name": "[concat(variables('huntingQueryTemplateSpecName13'),'/',variables('huntingQueryVersion13'))]", + "type": "Microsoft.OperationalInsights/workspaces/providers/contentTemplates", + "apiVersion": "2023-04-01-preview", + "name": "[variables('analyticRuleTemplateSpecName12')]", "location": "[parameters('workspace-location')]", - "tags": { - "hidden-sentinelWorkspaceId": "[variables('workspaceResourceId')]", - "hidden-sentinelContentType": "HuntingQuery" - }, "dependsOn": [ - "[resourceId('Microsoft.Resources/templateSpecs', variables('huntingQueryTemplateSpecName13'))]" + "[extensionResourceId(resourceId('Microsoft.OperationalInsights/workspaces', parameters('workspace')), 'Microsoft.SecurityInsights/contentPackages', variables('_solutionId'))]" ], "properties": { - "description": "PortOpenedForAzureResource_HuntingQueries Hunting Query with template version 2.0.6", + "description": "TimeSeriesAnomaly_Mass_Cloud_Resource_Deletions_AnalyticalRules Analytics Rule with template version 3.0.0", "mainTemplate": { "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", - "contentVersion": "[variables('huntingQueryVersion13')]", + "contentVersion": "[variables('analyticRuleVersion12')]", "parameters": {}, "variables": {}, "resources": [ { - "type": "Microsoft.OperationalInsights/savedSearches", - "apiVersion": "2020-08-01", - "name": "Azure_Activity_Hunting_Query_13", + "type": "Microsoft.SecurityInsights/AlertRuleTemplates", + "name": "[variables('analyticRulecontentId12')]", + "apiVersion": "2022-04-01-preview", + "kind": "Scheduled", "location": "[parameters('workspace-location')]", "properties": { - "eTag": "*", - "displayName": "Port opened for an Azure Resource", - "category": "Hunting Queries", - "query": "let lookback = 7d;\nAzureActivity\n| where TimeGenerated >= ago(lookback)\n| where OperationNameValue has_any (\"ipfilterrules\", \"securityRules\", \"publicIPAddresses\", \"firewallrules\") and OperationNameValue endswith \"write\"\n// Choosing Accepted here because it has the Rule Attributes included\n| where ActivityStatusValue == \"Accepted\" \n// If there is publicIP info, include it\n| extend parsed_properties = parse_json(tostring(parse_json(Properties).responseBody)).properties\n| extend publicIPAddressVersion = case(Properties has_cs 'publicIPAddressVersion',tostring(parsed_properties.publicIPAddressVersion),\"\")\n| extend publicIPAllocationMethod = case(Properties has_cs 'publicIPAllocationMethod',tostring(parsed_properties.publicIPAllocationMethod),\"\")\n// Include rule attributes for context\n| extend access = case(Properties has_cs 'access',tostring(parsed_properties.access),\"\")\n| extend description = case(Properties has_cs 'description',tostring(parsed_properties.description),\"\")\n| extend destinationPortRange = case(Properties has_cs 'destinationPortRange',tostring(parsed_properties.destinationPortRange),\"\")\n| extend direction = case(Properties has_cs 'direction',tostring(parsed_properties.direction),\"\")\n| extend protocol = case(Properties has_cs 'protocol',tostring(parsed_properties.protocol),\"\")\n| extend sourcePortRange = case(Properties has_cs 'sourcePortRange',tostring(parsed_properties.sourcePortRange),\"\")\n| summarize StartTime = min(TimeGenerated), EndTime = max(TimeGenerated), ResourceIds = make_set(_ResourceId,100) by Caller, CallerIpAddress, Resource, ResourceGroup, \nActivityStatusValue, ActivitySubstatus, SubscriptionId, access, description, destinationPortRange, direction, protocol, sourcePortRange, publicIPAddressVersion, publicIPAllocationMethod\n| extend Name = tostring(split(Caller,'@',0)[0]), UPNSuffix = tostring(split(Caller,'@',1)[0])\n| extend Account_0_Name = Name\n| extend Account_0_UPNSuffix = UPNSuffix\n| extend IP_0_Address = CallerIpAddress\n", - "version": 2, - "tags": [ - { - "name": "description", - "value": "Identifies what ports may have been opened for a given Azure Resource over the last 7 days" - }, + "description": "This query generates the baseline pattern of cloud resource deletions by an individual and generates an anomaly when any unusual spike is detected. These anomalies from unusual or privileged users could be an indication of a cloud infrastructure takedown by an adversary.", + "displayName": "Mass Cloud resource deletions Time Series Anomaly", + "enabled": false, + "query": "let starttime = 14d;\nlet endtime = 1d;\nlet timeframe = 1d;\nlet TotalEventsThreshold = 25;\nlet TimeSeriesData = AzureActivity \n| where TimeGenerated between (startofday(ago(starttime))..startofday(now())) \n| where OperationNameValue endswith \"delete\" \n| project TimeGenerated, Caller \n| make-series Total = count() on TimeGenerated from startofday(ago(starttime)) to startofday(now()) step timeframe by Caller;\nTimeSeriesData \n| extend (anomalies, score, baseline) = series_decompose_anomalies(Total, 3, -1, 'linefit') \n| mv-expand Total to typeof(double), TimeGenerated to typeof(datetime), anomalies to typeof(double), score to typeof(double), baseline to typeof(long) \n| where TimeGenerated >= startofday(ago(endtime)) \n| where anomalies > 0 \n| project Caller, TimeGenerated, Total, baseline, anomalies, score \n| where Total > TotalEventsThreshold and baseline > 0 \n| join (AzureActivity \n| where TimeGenerated > startofday(ago(endtime)) \n| where OperationNameValue endswith \"delete\" \n| summarize count(), make_set(OperationNameValue,100), make_set(_ResourceId,100) by bin(TimeGenerated, timeframe), Caller ) on TimeGenerated, Caller \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 '@',Caller,\"\")\n", + "queryFrequency": "P1D", + "queryPeriod": "P14D", + "severity": "Medium", + "suppressionDuration": "PT1H", + "suppressionEnabled": false, + "triggerOperator": "GreaterThan", + "triggerThreshold": 0, + "status": "Available", + "requiredDataConnectors": [ { - "name": "tactics", - "value": "CommandAndControl,Impact" - }, + "connectorId": "AzureActivity", + "dataTypes": [ + "AzureActivity" + ] + } + ], + "tactics": [ + "Impact" + ], + "techniques": [ + "T1485" + ], + "entityMappings": [ { - "name": "techniques", - "value": "T1071,T1571,T1496" + "fieldMappings": [ + { + "identifier": "Name", + "columnName": "Name" + }, + { + "identifier": "UPNSuffix", + "columnName": "UPNSuffix" + }, + { + "identifier": "AadUserId", + "columnName": "AadUserId" + } + ], + "entityType": "Account" } ] } @@ -1524,13 +1856,13 @@ { "type": "Microsoft.OperationalInsights/workspaces/providers/metadata", "apiVersion": "2022-01-01-preview", - "name": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/',concat('HuntingQuery-', last(split(variables('huntingQueryId13'),'/'))))]", + "name": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/',concat('AnalyticsRule-', last(split(variables('analyticRuleId12'),'/'))))]", "properties": { - "description": "Azure Activity Hunting Query 13", - "parentId": "[variables('huntingQueryId13')]", - "contentId": "[variables('_huntingQuerycontentId13')]", - "kind": "HuntingQuery", - "version": "[variables('huntingQueryVersion13')]", + "description": "Azure Activity Analytics Rule 12", + "parentId": "[variables('analyticRuleId12')]", + "contentId": "[variables('_analyticRulecontentId12')]", + "kind": "AnalyticsRule", + "version": "[variables('analyticRuleVersion12')]", "source": { "kind": "Solution", "name": "Azure Activity", @@ -1549,66 +1881,59 @@ } } ] - } - } - }, - { - "type": "Microsoft.Resources/templateSpecs", - "apiVersion": "2022-02-01", - "name": "[variables('huntingQueryTemplateSpecName14')]", - "location": "[parameters('workspace-location')]", - "tags": { - "hidden-sentinelWorkspaceId": "[variables('workspaceResourceId')]", - "hidden-sentinelContentType": "HuntingQuery" - }, - "properties": { - "description": "Azure Activity Hunting Query 14 with template", - "displayName": "Azure Activity Hunting Query template" + }, + "packageKind": "Solution", + "packageVersion": "[variables('_solutionVersion')]", + "packageName": "[variables('_solutionName')]", + "packageId": "[variables('_solutionId')]", + "contentSchemaVersion": "3.0.0", + "contentId": "[variables('_analyticRulecontentId12')]", + "contentKind": "AnalyticsRule", + "displayName": "Mass Cloud resource deletions Time Series Anomaly", + "contentProductId": "[variables('_analyticRulecontentProductId12')]", + "id": "[variables('_analyticRulecontentProductId12')]", + "version": "[variables('analyticRuleVersion12')]" } }, { - "type": "Microsoft.Resources/templateSpecs/versions", - "apiVersion": "2022-02-01", - "name": "[concat(variables('huntingQueryTemplateSpecName14'),'/',variables('huntingQueryVersion14'))]", + "type": "Microsoft.OperationalInsights/workspaces/providers/contentTemplates", + "apiVersion": "2023-04-01-preview", + "name": "[variables('huntingQueryTemplateSpecName1')]", "location": "[parameters('workspace-location')]", - "tags": { - "hidden-sentinelWorkspaceId": "[variables('workspaceResourceId')]", - "hidden-sentinelContentType": "HuntingQuery" - }, "dependsOn": [ - "[resourceId('Microsoft.Resources/templateSpecs', variables('huntingQueryTemplateSpecName14'))]" + "[extensionResourceId(resourceId('Microsoft.OperationalInsights/workspaces', parameters('workspace')), 'Microsoft.SecurityInsights/contentPackages', variables('_solutionId'))]" ], "properties": { - "description": "Rare_Custom_Script_Extension_HuntingQueries Hunting Query with template version 2.0.6", + "description": "AnalyticsRulesAdministrativeOperations_HuntingQueries Hunting Query with template version 3.0.0", "mainTemplate": { "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", - "contentVersion": "[variables('huntingQueryVersion14')]", + "contentVersion": "[variables('huntingQueryVersion1')]", "parameters": {}, "variables": {}, "resources": [ { "type": "Microsoft.OperationalInsights/savedSearches", - "apiVersion": "2020-08-01", - "name": "Azure_Activity_Hunting_Query_14", + "apiVersion": "2022-10-01", + "name": "Azure_Activity_Hunting_Query_1", "location": "[parameters('workspace-location')]", "properties": { "eTag": "*", - "displayName": "Rare Custom Script Extension", + "displayName": "Microsoft Sentinel Analytics Rules Administrative Operations", "category": "Hunting Queries", - "query": "let starttime = todatetime('{{StartTimeISO}}');\nlet endtime = todatetime('{{EndTimeISO}}');\nlet Lookback = starttime - 14d;\nlet CustomScriptExecution = AzureActivity\n| where TimeGenerated >= Lookback\n| where OperationName =~ \"Create or Update Virtual Machine Extension\"\n| extend parsed_properties = parse_json(Properties)\n| extend Settings = tostring((parse_json(tostring(parsed_properties.responseBody)).properties).settings)\n| parse Settings with * 'fileUris\":[' FileURI \"]\" *\n| parse Settings with * 'commandToExecute\":' commandToExecute '}' *\n| extend message_ = tostring((parse_json(tostring(parsed_properties.statusMessage)).error).message);\nlet LookbackCustomScriptExecution = CustomScriptExecution\n| where TimeGenerated >= Lookback and TimeGenerated < starttime\n| where isnotempty(FileURI) and isnotempty(commandToExecute)\n| summarize max(TimeGenerated), OperationCount = count() by Caller, Resource, CallerIpAddress, FileURI, commandToExecute;\nlet CurrentCustomScriptExecution = CustomScriptExecution\n| where TimeGenerated between (starttime..endtime)\n| where isnotempty(FileURI) and isnotempty(commandToExecute)\n| project TimeGenerated, ActivityStatus, OperationId, CorrelationId, ResourceId, CallerIpAddress, Caller, OperationName, Resource, ResourceGroup, FileURI, commandToExecute, FailureMessage = message_, HTTPRequest, Settings;\nlet RareCustomScriptExecution = CurrentCustomScriptExecution\n| join kind= leftanti (LookbackCustomScriptExecution) on Caller, CallerIpAddress, FileURI, commandToExecute;\nlet IPCheck = RareCustomScriptExecution\n| summarize arg_max(TimeGenerated, OperationName), OperationIds = make_set(OperationId,100), CallerIpAddresses = make_set(CallerIpAddress,100) by ActivityStatus, CorrelationId, ResourceId, Caller, Resource, ResourceGroup, FileURI, commandToExecute, FailureMessage\n| extend IPArray = array_length(CallerIpAddresses);\n//Get IPs for later summarization so all associated CorrelationIds and Caller actions have an IP. Success and Fails do not always have IP\nlet multiIP = IPCheck | where IPArray > 1\n| mv-expand CallerIpAddresses | extend CallerIpAddress = tostring(CallerIpAddresses)\n| where isnotempty(CallerIpAddresses);\nlet singleIP = IPCheck | where IPArray <= 1\n| mv-expand CallerIpAddresses | extend CallerIpAddress = tostring(CallerIpAddresses);\nlet FullDetails = singleIP | union multiIP;\n//Get IP address associated with successes and fails with no IP listed\nlet IPList = FullDetails | where isnotempty(CallerIpAddress) | summarize by CorrelationId, Caller, CallerIpAddress;\nlet EmptyIP = FullDetails | where isempty(CallerIpAddress) | project-away CallerIpAddress;\nlet IpJoin = EmptyIP | join kind= leftouter (IPList) on CorrelationId, Caller | project-away CorrelationId1, Caller1;\nlet nonEmptyIP = FullDetails | where isnotempty(CallerIpAddress);\nnonEmptyIP | union IpJoin\n// summarize all activities with a given CorrelationId and Caller together so we can provide a singular result\n| summarize StartTime = min(TimeGenerated), EndTime = max(TimeGenerated), ActivityStatusSet = make_set(ActivityStatus,100), OperationIds = make_set(OperationIds,100), FailureMessages = make_set(FailureMessage,100) by CorrelationId, ResourceId, CallerIpAddress, Caller, Resource, ResourceGroup, FileURI, commandToExecute\n| extend Name = tostring(split(Caller,'@',0)[0]), UPNSuffix = tostring(split(Caller,'@',1)[0])\n| extend Account_0_Name = Name\n| extend Account_0_UPNSuffix = UPNSuffix\n| extend IP_0_Address = CallerIpAddress\n", + "query": "let opValues = dynamic([\"Microsoft.SecurityInsights/alertRules/write\", \"Microsoft.SecurityInsights/alertRules/delete\"]);\n// Microsoft Sentinel Analytics - Rule Create / Update / Delete\nAzureActivity\n| where Category =~ \"Administrative\"\n| where OperationNameValue in~ (opValues)\n| where ActivitySubstatusValue in~ (\"Created\", \"OK\")\n| sort by TimeGenerated desc\n| extend Name = tostring(split(Caller,'@',0)[0]), UPNSuffix = tostring(split(Caller,'@',1)[0])\n| extend Account_0_Name = Name\n| extend Account_0_UPNSuffix = UPNSuffix\n| extend IP_0_Address = CallerIpAddress\n", "version": 2, "tags": [ { "name": "description", - "value": "The Custom Script Extension downloads and executes scripts on Azure virtual machines. This extension is useful for post deployment configuration, software installation, or any other configuration or management tasks.\n Scripts could be downloaded from external links, Azure storage, GitHub, or provided to the Azure portal at extension run time. This could also be used maliciously by an attacker.\n The query tries to identify rare custom script extensions that have been executed in your environment" + "value": "Identifies Microsoft Sentinel Analytics Rules administrative operations" }, { "name": "tactics", - "value": "Execution" + "value": "Impact" }, { "name": "techniques", - "value": "T1059" + "value": "T1496" } ] } @@ -1616,13 +1941,13 @@ { "type": "Microsoft.OperationalInsights/workspaces/providers/metadata", "apiVersion": "2022-01-01-preview", - "name": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/',concat('HuntingQuery-', last(split(variables('huntingQueryId14'),'/'))))]", + "name": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/',concat('HuntingQuery-', last(split(variables('huntingQueryId1'),'/'))))]", "properties": { - "description": "Azure Activity Hunting Query 14", - "parentId": "[variables('huntingQueryId14')]", - "contentId": "[variables('_huntingQuerycontentId14')]", + "description": "Azure Activity Hunting Query 1", + "parentId": "[variables('huntingQueryId1')]", + "contentId": "[variables('_huntingQuerycontentId1')]", "kind": "HuntingQuery", - "version": "[variables('huntingQueryVersion14')]", + "version": "[variables('huntingQueryVersion1')]", "source": { "kind": "Solution", "name": "Azure Activity", @@ -1641,98 +1966,59 @@ } } ] - } - } - }, - { - "type": "Microsoft.Resources/templateSpecs", - "apiVersion": "2022-02-01", - "name": "[variables('analyticRuleTemplateSpecName1')]", - "location": "[parameters('workspace-location')]", - "tags": { - "hidden-sentinelWorkspaceId": "[variables('workspaceResourceId')]", - "hidden-sentinelContentType": "AnalyticsRule" - }, - "properties": { - "description": "Azure Activity Analytics Rule 1 with template", - "displayName": "Azure Activity Analytics Rule template" + }, + "packageKind": "Solution", + "packageVersion": "[variables('_solutionVersion')]", + "packageName": "[variables('_solutionName')]", + "packageId": "[variables('_solutionId')]", + "contentSchemaVersion": "3.0.0", + "contentId": "[variables('_huntingQuerycontentId1')]", + "contentKind": "HuntingQuery", + "displayName": "Microsoft Sentinel Analytics Rules Administrative Operations", + "contentProductId": "[variables('_huntingQuerycontentProductId1')]", + "id": "[variables('_huntingQuerycontentProductId1')]", + "version": "[variables('huntingQueryVersion1')]" } }, { - "type": "Microsoft.Resources/templateSpecs/versions", - "apiVersion": "2022-02-01", - "name": "[concat(variables('analyticRuleTemplateSpecName1'),'/',variables('analyticRuleVersion1'))]", + "type": "Microsoft.OperationalInsights/workspaces/providers/contentTemplates", + "apiVersion": "2023-04-01-preview", + "name": "[variables('huntingQueryTemplateSpecName2')]", "location": "[parameters('workspace-location')]", - "tags": { - "hidden-sentinelWorkspaceId": "[variables('workspaceResourceId')]", - "hidden-sentinelContentType": "AnalyticsRule" - }, "dependsOn": [ - "[resourceId('Microsoft.Resources/templateSpecs', variables('analyticRuleTemplateSpecName1'))]" + "[extensionResourceId(resourceId('Microsoft.OperationalInsights/workspaces', parameters('workspace')), 'Microsoft.SecurityInsights/contentPackages', variables('_solutionId'))]" ], "properties": { - "description": "AADHybridHealthADFSNewServer_AnalyticalRules Analytics Rule with template version 2.0.6", + "description": "AnomalousAzureOperationModel_HuntingQueries Hunting Query with template version 3.0.0", "mainTemplate": { "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", - "contentVersion": "[variables('analyticRuleVersion1')]", + "contentVersion": "[variables('huntingQueryVersion2')]", "parameters": {}, "variables": {}, "resources": [ { - "type": "Microsoft.SecurityInsights/AlertRuleTemplates", - "name": "[variables('AnalyticRulecontentId1')]", - "apiVersion": "2022-04-01-preview", - "kind": "Scheduled", + "type": "Microsoft.OperationalInsights/savedSearches", + "apiVersion": "2022-10-01", + "name": "Azure_Activity_Hunting_Query_2", "location": "[parameters('workspace-location')]", "properties": { - "description": "This detection uses AzureActivity logs (Administrative category) to identify the creation or update of a server instance in an Azure AD Hybrid Health AD FS service.\nA threat actor can create a new AD Health ADFS service and create a fake server instance to spoof AD FS signing logs. There is no need to compromise an on-premises AD FS server.\nThis can be done programmatically via HTTP requests to Azure. More information in this blog: https://o365blog.com/post/hybridhealthagent/", - "displayName": "Azure Active Directory Hybrid Health AD FS New Server", - "enabled": false, - "query": "AzureActivity\n| where CategoryValue =~ 'Administrative'\n| where ResourceProviderValue =~ 'Microsoft.ADHybridHealthService'\n| where _ResourceId has 'AdFederationService'\n| where OperationNameValue =~ 'Microsoft.ADHybridHealthService/services/servicemembers/action'\n| extend claimsJson = parse_json(Claims)\n| extend AppId = tostring(claimsJson.appid), AccountName = tostring(claimsJson.name), Name = tostring(split(Caller,'@',0)[0]), UPNSuffix = tostring(split(Caller,'@',1)[0])\n| project-away claimsJson\n", - "queryFrequency": "P1D", - "queryPeriod": "P1D", - "severity": "Medium", - "suppressionDuration": "PT1H", - "suppressionEnabled": false, - "triggerOperator": "GreaterThan", - "triggerThreshold": 0, - "status": "Available", - "requiredDataConnectors": [ + "eTag": "*", + "displayName": "Anomalous Azure Operation Hunting Model", + "category": "Hunting Queries", + "query": "// When the detection window will end (3 days prior to now)\nlet startDetectDate = 3d;\n// When the detection window will start (now)\nlet endDetectDate = 0d;\n// When to start collecting data for detection\nlet startDate = startDetectDate + 30d;\n// Operation to monitor, in this case Run Command\nlet monitoredOps = dynamic(['microsoft.compute/virtualmachines/runcommand/action']);\n// The resource type to monitor, in this case virtual machines\nlet monitoredResource = pack_array('microsoft.compute/virtualmachines');\nlet pair_probabilities_fl = (tbl:(*), A_col:string, B_col:string, scope_col:string)\n{\nlet T = (tbl | extend _A = column_ifexists(A_col, ''), _B = column_ifexists(B_col, ''), _scope = column_ifexists(scope_col, ''));\nlet countOnScope = T | summarize countAllOnScope = count() by _scope;\nlet probAB = T | summarize countAB = count() by _A, _B, _scope | join kind = leftouter (countOnScope) on _scope | extend P_AB = todouble(countAB)/countAllOnScope;\nlet probA = probAB | summarize countA = sum(countAB), countAllOnScope = max(countAllOnScope) by _A, _scope | extend P_A = todouble(countA)/countAllOnScope;\nlet probB = probAB | summarize countB = sum(countAB), countAllOnScope = max(countAllOnScope) by _B, _scope | extend P_B = todouble(countB)/countAllOnScope;\n probAB\n | join kind = leftouter (probA) on _A, _scope\n | join kind = leftouter (probB) on _B, _scope\n | extend P_AUB = P_A + P_B - P_AB\n , P_AIB = P_AB/P_B\n , P_BIA = P_AB/P_A\n | extend Lift_AB = P_AB/(P_A * P_B)\n , Jaccard_AB = P_AB/P_AUB\n | project _A, _B, _scope, floor(P_A, 0.00001), floor(P_B, 0.00001), floor(P_AB, 0.00001), floor(P_AUB, 0.00001), floor(P_AIB, 0.00001)\n , floor(P_BIA, 0.00001), floor(Lift_AB, 0.00001), floor(Jaccard_AB, 0.00001)\n | sort by _scope, _A, _B\n};\nlet eventsTable = materialize (\nAzureActivity\n| where TimeGenerated between (ago(startDate) .. ago(endDetectDate))\n| where isnotempty(CallerIpAddress)\n| where ActivityStatusValue has_any ('Success', 'Succeeded')\n| extend ResourceId = iff(isempty(_ResourceId), ResourceId, _ResourceId)\n| extend splitOp = split(OperationNameValue, '/')\n| extend splitRes = split(ResourceId, '/')\n| project TimeGenerated , subscriptionId=SubscriptionId\n , ResourceProvider\n , ResourceName = tolower(tostring(splitRes[-1]))\n , OperationNameValue = tolower(OperationNameValue)\n , timeSlice = floor(TimeGenerated, 1d)\n , clientIp = tostring(CallerIpAddress)\n , Caller\n , isMonitoredOp = iff(OperationNameValue has_any (monitoredOps), 1, 0)\n , isMonitoredResource = iff(OperationNameValue has_any (monitoredResource), 1, 0)\n , CorrelationId\n| extend clientIpMask = format_ipv4_mask(clientIp, 16)\n);\nlet modelData = (\neventsTable\n| where TimeGenerated < ago(startDetectDate) and isnotempty(Caller) and isnotempty(subscriptionId)\n| summarize countEvents = count(), countMonRes = countif(isMonitoredResource == 1), counMonOp = countif(isMonitoredOp == 1)\n , firstSeen = min(timeSlice), firstSeenOnMonRes = minif(timeSlice, isMonitoredResource == 1), firstSeenOnMonOp = minif(timeSlice, isMonitoredOp == 1)\n by subscriptionId, Caller, clientIpMask\n);\nlet monOpProbs = materialize (\neventsTable\n| where TimeGenerated < ago(startDetectDate) and isnotempty(Caller) and isnotempty(subscriptionId)\n| invoke pair_probabilities_fl('Caller', 'isMonitoredResource','subscriptionId')\n| where _B == 1\n| sort by P_AIB desc\n| extend rankOnMonRes = row_rank(P_AIB), sumBiggerCondProbs = row_cumsum(P_AIB) - P_AIB\n| extend avgBiggerCondProbs = floor(iff(rankOnMonRes > 1, sumBiggerCondProbs/(rankOnMonRes-1), max_of(0.0, prev(sumBiggerCondProbs))), 0.00001)\n| project-away sumBiggerCondProbs\n);\neventsTable\n| where TimeGenerated between (ago(startDetectDate) .. ago(endDetectDate))\n| join kind = leftouter (modelData | summarize countEventsPrincOnSub = sum(countEvents), countEventsMonResPrincOnSub = sum(countMonRes), countEventsMonOpPrincOnSub = sum(counMonOp)\n , firstSeenPrincOnSubs = min(firstSeen), firstSeenMonResPrincOnSubs = min(firstSeenOnMonRes), firstSeenMonOpPrincOnSubs = min(firstSeenOnMonOp) by subscriptionId, Caller) \n on subscriptionId, Caller\n| join kind = leftouter (modelData | summarize countEventsIpMaskOnSub = sum(countEvents), countEventsMonResIpMaskOnSub = sum(countMonRes), countEventsMonOpIpMaskOnSub = sum(counMonOp)\n , firstSeenIpMaskOnSubs = min(firstSeen), firstSeenMonResIpMaskOnSubs = min(firstSeenOnMonRes), firstSeenMonOpIpMaskOnSubs = min(firstSeenOnMonOp) by subscriptionId, clientIpMask) \n on subscriptionId, clientIpMask\n| join kind = leftouter (modelData | summarize countEventsOnSub = sum(countEvents), countEventsMonResOnSub = sum(countMonRes), countEventsMonOpOnSub = sum(counMonOp)\n , firstSeenOnSubs = min(firstSeen), firstSeenMonResOnSubs = min(firstSeenOnMonRes), firstSeenMonOpOnSubs = min(firstSeenOnMonOp)\n , countCallersOnSubs = dcount(Caller), countIpMasksOnSubs = dcount(clientIpMask) by subscriptionId)\n on subscriptionId \n| project-away subscriptionId1, Caller1, subscriptionId2\n| extend daysOnSubs = datetime_diff('day', timeSlice, firstSeenOnSubs)\n| extend avgMonOpOnSubs = floor(1.0*countEventsMonOpOnSub/daysOnSubs, 0.01), avgMonResOnSubs = floor(1.0*countEventsMonResOnSub/daysOnSubs, 0.01)\n| join kind = leftouter(monOpProbs) on $left.subscriptionId == $right._scope, $left.Caller == $right._A\n| project-away _A, _B, _scope\n| sort by subscriptionId asc, TimeGenerated asc\n| extend rnOnSubs = row_number(1, subscriptionId != prev(subscriptionId))\n| sort by subscriptionId asc, Caller asc, TimeGenerated asc\n| extend rnOnCallerSubs = row_number(1, (subscriptionId != prev(subscriptionId) and (Caller != prev(Caller))))\n| extend newCaller = iff(isempty(firstSeenPrincOnSubs), 1, 0)\n , newCallerOnMonRes = iff(isempty(firstSeenMonResPrincOnSubs), 1, 0)\n , newIpMask = iff(isempty(firstSeenIpMaskOnSubs), 1, 0)\n , newIpMaskOnMonRes = iff(isempty(firstSeenMonResIpMaskOnSubs), 1, 0)\n , newMonOpOnSubs = iff(isempty(firstSeenMonResOnSubs), 1, 0)\n , anomCallerMonRes = iff(((Jaccard_AB <= 0.1) or (P_AIB <= 0.1)), 1, 0)\n| project TimeGenerated, subscriptionId, ResourceProvider, ResourceName, OperationNameValue, Caller, CorrelationId, ClientIP=clientIp, ActiveDaysOnSub=daysOnSubs, avgMonOpOnSubs, newCaller, newCallerOnMonRes, newIpMask, newIpMaskOnMonRes, newMonOpOnSubs, anomCallerMonRes, isMonitoredOp, isMonitoredResource\n| order by TimeGenerated\n| where isMonitoredOp == 1\n// Optional - focus only on monitored operations or monitored resource in detection window\n| where isMonitoredOp == 1\n//| where isMonitoredResource == 1\n", + "version": 2, + "tags": [ { - "dataTypes": [ - "AzureActivity" - ], - "connectorId": "AzureActivity" - } - ], - "tactics": [ - "DefenseEvasion" - ], - "techniques": [ - "T1578" - ], - "entityMappings": [ + "name": "description", + "value": "This query identifies Azure Operation anomalies during threat hunts. It detects new callers, IPs, IP ranges, and anomalous operations. Initially set for Run Command operations, it can be configured for other operations and resource types." + }, { - "entityType": "Account", - "fieldMappings": [ - { - "columnName": "Name", - "identifier": "Name" - }, - { - "columnName": "UPNSuffix", - "identifier": "UPNSuffix" - } - ] + "name": "tactics", + "value": "LateralMovement,CredentialAccess" }, { - "entityType": "IP", - "fieldMappings": [ - { - "columnName": "CallerIpAddress", - "identifier": "Address" - } - ] + "name": "techniques", + "value": "T1570,T1078.004" } ] } @@ -1740,13 +2026,13 @@ { "type": "Microsoft.OperationalInsights/workspaces/providers/metadata", "apiVersion": "2022-01-01-preview", - "name": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/',concat('AnalyticsRule-', last(split(variables('analyticRuleId1'),'/'))))]", + "name": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/',concat('HuntingQuery-', last(split(variables('huntingQueryId2'),'/'))))]", "properties": { - "description": "Azure Activity Analytics Rule 1", - "parentId": "[variables('analyticRuleId1')]", - "contentId": "[variables('_analyticRulecontentId1')]", - "kind": "AnalyticsRule", - "version": "[variables('analyticRuleVersion1')]", + "description": "Azure Activity Hunting Query 2", + "parentId": "[variables('huntingQueryId2')]", + "contentId": "[variables('_huntingQuerycontentId2')]", + "kind": "HuntingQuery", + "version": "[variables('huntingQueryVersion2')]", "source": { "kind": "Solution", "name": "Azure Activity", @@ -1765,98 +2051,59 @@ } } ] - } - } - }, - { - "type": "Microsoft.Resources/templateSpecs", - "apiVersion": "2022-02-01", - "name": "[variables('analyticRuleTemplateSpecName2')]", - "location": "[parameters('workspace-location')]", - "tags": { - "hidden-sentinelWorkspaceId": "[variables('workspaceResourceId')]", - "hidden-sentinelContentType": "AnalyticsRule" - }, - "properties": { - "description": "Azure Activity Analytics Rule 2 with template", - "displayName": "Azure Activity Analytics Rule template" + }, + "packageKind": "Solution", + "packageVersion": "[variables('_solutionVersion')]", + "packageName": "[variables('_solutionName')]", + "packageId": "[variables('_solutionId')]", + "contentSchemaVersion": "3.0.0", + "contentId": "[variables('_huntingQuerycontentId2')]", + "contentKind": "HuntingQuery", + "displayName": "Anomalous Azure Operation Hunting Model", + "contentProductId": "[variables('_huntingQuerycontentProductId2')]", + "id": "[variables('_huntingQuerycontentProductId2')]", + "version": "[variables('huntingQueryVersion2')]" } }, { - "type": "Microsoft.Resources/templateSpecs/versions", - "apiVersion": "2022-02-01", - "name": "[concat(variables('analyticRuleTemplateSpecName2'),'/',variables('analyticRuleVersion2'))]", + "type": "Microsoft.OperationalInsights/workspaces/providers/contentTemplates", + "apiVersion": "2023-04-01-preview", + "name": "[variables('huntingQueryTemplateSpecName3')]", "location": "[parameters('workspace-location')]", - "tags": { - "hidden-sentinelWorkspaceId": "[variables('workspaceResourceId')]", - "hidden-sentinelContentType": "AnalyticsRule" - }, "dependsOn": [ - "[resourceId('Microsoft.Resources/templateSpecs', variables('analyticRuleTemplateSpecName2'))]" + "[extensionResourceId(resourceId('Microsoft.OperationalInsights/workspaces', parameters('workspace')), 'Microsoft.SecurityInsights/contentPackages', variables('_solutionId'))]" ], "properties": { - "description": "AADHybridHealthADFSServiceDelete_AnalyticalRules Analytics Rule with template version 2.0.6", + "description": "Anomalous_Listing_Of_Storage_Keys_HuntingQueries Hunting Query with template version 3.0.0", "mainTemplate": { "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", - "contentVersion": "[variables('analyticRuleVersion2')]", + "contentVersion": "[variables('huntingQueryVersion3')]", "parameters": {}, "variables": {}, "resources": [ { - "type": "Microsoft.SecurityInsights/AlertRuleTemplates", - "name": "[variables('AnalyticRulecontentId2')]", - "apiVersion": "2022-04-01-preview", - "kind": "Scheduled", + "type": "Microsoft.OperationalInsights/savedSearches", + "apiVersion": "2022-10-01", + "name": "Azure_Activity_Hunting_Query_3", "location": "[parameters('workspace-location')]", "properties": { - "description": "This detection uses AzureActivity logs (Administrative category) to identify the deletion of an Azure AD Hybrid Health AD FS service instance in a tenant.\nA threat actor can create a new AD Health ADFS service and create a fake server to spoof AD FS signing logs.\nThe health AD FS service can then be deleted after it is no longer needed via HTTP requests to Azure.\nMore information is available in this blog https://o365blog.com/post/hybridhealthagent/", - "displayName": "Azure Active Directory Hybrid Health AD FS Service Delete", - "enabled": false, - "query": "AzureActivity\n| where CategoryValue =~ 'Administrative'\n| where ResourceProviderValue =~ 'Microsoft.ADHybridHealthService'\n| where _ResourceId has 'AdFederationService'\n| where OperationNameValue =~ 'Microsoft.ADHybridHealthService/services/delete'\n| extend claimsJson = parse_json(Claims)\n| extend AppId = tostring(claimsJson.appid), AccountName = tostring(claimsJson.name), Name = tostring(split(Caller,'@',0)[0]), UPNSuffix = tostring(split(Caller,'@',1)[0])\n| project-away claimsJson\n", - "queryFrequency": "P1D", - "queryPeriod": "P1D", - "severity": "Medium", - "suppressionDuration": "PT1H", - "suppressionEnabled": false, - "triggerOperator": "GreaterThan", - "triggerThreshold": 0, - "status": "Available", - "requiredDataConnectors": [ + "eTag": "*", + "displayName": "Azure storage key enumeration", + "category": "Hunting Queries", + "query": "AzureActivity\n| where OperationNameValue =~ \"microsoft.storage/storageaccounts/listkeys/action\"\n| where ActivityStatusValue =~ \"Succeeded\" \n| join kind= inner (\n AzureActivity\n | where OperationNameValue =~ \"microsoft.storage/storageaccounts/listkeys/action\"\n | where ActivityStatusValue =~ \"Succeeded\" \n | project ExpectedIpAddress=CallerIpAddress, Caller \n | evaluate autocluster()\n) on Caller\n| where CallerIpAddress != ExpectedIpAddress\n| summarize StartTime = min(TimeGenerated), EndTime = max(TimeGenerated), ResourceIds = make_set(ResourceId,100), ResourceIdCount = dcount(ResourceId) by OperationNameValue, Caller, CallerIpAddress\n| extend Name = tostring(split(Caller,'@',0)[0]), UPNSuffix = tostring(split(Caller,'@',1)[0])\n| extend Account_0_Name = Name\n| extend Account_0_UPNSuffix = UPNSuffix\n| extend IP_0_Address = CallerIpAddress\n", + "version": 2, + "tags": [ { - "dataTypes": [ - "AzureActivity" - ], - "connectorId": "AzureActivity" - } - ], - "tactics": [ - "DefenseEvasion" - ], - "techniques": [ - "T1578" - ], - "entityMappings": [ + "name": "description", + "value": "Azure's storage key listing can expose secrets, PII, and grant VM access. Monitoring for anomalous accounts or IPs is crucial. The query generates IP clusters, correlates activities, and flags unexpected ones. Single-operation users are excluded." + }, { - "entityType": "Account", - "fieldMappings": [ - { - "columnName": "Name", - "identifier": "Name" - }, - { - "columnName": "UPNSuffix", - "identifier": "UPNSuffix" - } - ] + "name": "tactics", + "value": "Discovery" }, { - "entityType": "IP", - "fieldMappings": [ - { - "columnName": "CallerIpAddress", - "identifier": "Address" - } - ] + "name": "techniques", + "value": "T1087" } ] } @@ -1864,13 +2111,13 @@ { "type": "Microsoft.OperationalInsights/workspaces/providers/metadata", "apiVersion": "2022-01-01-preview", - "name": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/',concat('AnalyticsRule-', last(split(variables('analyticRuleId2'),'/'))))]", + "name": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/',concat('HuntingQuery-', last(split(variables('huntingQueryId3'),'/'))))]", "properties": { - "description": "Azure Activity Analytics Rule 2", - "parentId": "[variables('analyticRuleId2')]", - "contentId": "[variables('_analyticRulecontentId2')]", - "kind": "AnalyticsRule", - "version": "[variables('analyticRuleVersion2')]", + "description": "Azure Activity Hunting Query 3", + "parentId": "[variables('huntingQueryId3')]", + "contentId": "[variables('_huntingQuerycontentId3')]", + "kind": "HuntingQuery", + "version": "[variables('huntingQueryVersion3')]", "source": { "kind": "Solution", "name": "Azure Activity", @@ -1889,100 +2136,59 @@ } } ] - } - } - }, - { - "type": "Microsoft.Resources/templateSpecs", - "apiVersion": "2022-02-01", - "name": "[variables('analyticRuleTemplateSpecName3')]", - "location": "[parameters('workspace-location')]", - "tags": { - "hidden-sentinelWorkspaceId": "[variables('workspaceResourceId')]", - "hidden-sentinelContentType": "AnalyticsRule" - }, - "properties": { - "description": "Azure Activity Analytics Rule 3 with template", - "displayName": "Azure Activity Analytics Rule template" + }, + "packageKind": "Solution", + "packageVersion": "[variables('_solutionVersion')]", + "packageName": "[variables('_solutionName')]", + "packageId": "[variables('_solutionId')]", + "contentSchemaVersion": "3.0.0", + "contentId": "[variables('_huntingQuerycontentId3')]", + "contentKind": "HuntingQuery", + "displayName": "Azure storage key enumeration", + "contentProductId": "[variables('_huntingQuerycontentProductId3')]", + "id": "[variables('_huntingQuerycontentProductId3')]", + "version": "[variables('huntingQueryVersion3')]" } }, { - "type": "Microsoft.Resources/templateSpecs/versions", - "apiVersion": "2022-02-01", - "name": "[concat(variables('analyticRuleTemplateSpecName3'),'/',variables('analyticRuleVersion3'))]", + "type": "Microsoft.OperationalInsights/workspaces/providers/contentTemplates", + "apiVersion": "2023-04-01-preview", + "name": "[variables('huntingQueryTemplateSpecName4')]", "location": "[parameters('workspace-location')]", - "tags": { - "hidden-sentinelWorkspaceId": "[variables('workspaceResourceId')]", - "hidden-sentinelContentType": "AnalyticsRule" - }, "dependsOn": [ - "[resourceId('Microsoft.Resources/templateSpecs', variables('analyticRuleTemplateSpecName3'))]" + "[extensionResourceId(resourceId('Microsoft.OperationalInsights/workspaces', parameters('workspace')), 'Microsoft.SecurityInsights/contentPackages', variables('_solutionId'))]" ], "properties": { - "description": "AADHybridHealthADFSSuspApp_AnalyticalRules Analytics Rule with template version 2.0.6", + "description": "AzureAdministrationFromVPS_HuntingQueries Hunting Query with template version 3.0.0", "mainTemplate": { "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", - "contentVersion": "[variables('analyticRuleVersion3')]", + "contentVersion": "[variables('huntingQueryVersion4')]", "parameters": {}, "variables": {}, "resources": [ { - "type": "Microsoft.SecurityInsights/AlertRuleTemplates", - "name": "[variables('AnalyticRulecontentId3')]", - "apiVersion": "2022-04-01-preview", - "kind": "Scheduled", + "type": "Microsoft.OperationalInsights/savedSearches", + "apiVersion": "2022-10-01", + "name": "Azure_Activity_Hunting_Query_4", "location": "[parameters('workspace-location')]", "properties": { - "description": "This detection uses AzureActivity logs (Administrative category) to identify a suspicious application adding a server instance to an Azure AD Hybrid Health AD FS service or deleting the AD FS service instance.\nUsually the Azure AD Connect Health Agent application with ID cf6d7e68-f018-4e0a-a7b3-126e053fb88d and ID cb1056e2-e479-49de-ae31-7812af012ed8 is used to perform those operations.", - "displayName": "Azure Active Directory Hybrid Health AD FS Suspicious Application", - "enabled": false, - "query": "// Azure AD Connect Health Agent - cf6d7e68-f018-4e0a-a7b3-126e053fb88d\n// Azure Active Directory Connect - cb1056e2-e479-49de-ae31-7812af012ed8\nlet appList = dynamic(['cf6d7e68-f018-4e0a-a7b3-126e053fb88d','cb1056e2-e479-49de-ae31-7812af012ed8']);\nlet operationNamesList = dynamic(['Microsoft.ADHybridHealthService/services/servicemembers/action','Microsoft.ADHybridHealthService/services/delete']);\nAzureActivity\n| where CategoryValue =~ 'Administrative'\n| where ResourceProviderValue =~ 'Microsoft.ADHybridHealthService'\n| where _ResourceId has 'AdFederationService'\n| where OperationNameValue in~ (operationNamesList)\n| extend claimsJson = parse_json(Claims)\n| extend AppId = tostring(claimsJson.appid), AccountName = tostring(claimsJson.name), Name = tostring(split(Caller,'@',0)[0]), UPNSuffix = tostring(split(Caller,'@',1)[0])\n| where AppId !in (appList)\n| project-away claimsJson\n", - "queryFrequency": "P1D", - "queryPeriod": "P1D", - "severity": "Medium", - "suppressionDuration": "PT1H", - "suppressionEnabled": false, - "triggerOperator": "GreaterThan", - "triggerThreshold": 0, - "status": "Available", - "requiredDataConnectors": [ + "eTag": "*", + "displayName": "AzureActivity Administration From VPS Providers", + "category": "Hunting Queries", + "query": "let IP_Data = (externaldata(network:string)\n[@\"https://raw.githubusercontent.com/Azure/Azure-Sentinel/master/Sample%20Data/Feeds/VPS_Networks.csv\"] with (format=\"csv\"));\nAzureActivity\n| where CategoryValue =~ \"Administrative\"\n| evaluate ipv4_lookup(IP_Data, CallerIpAddress, network, return_unmatched = false)\n| summarize Operations = make_set(OperationNameValue), StartTime = min(TimeGenerated), EndTime = max(TimeGenerated) by CallerIpAddress, Caller\n| extend Name = tostring(split(Caller,'@',0)[0]), UPNSuffix = tostring(split(Caller,'@',1)[0])\n| extend Account_0_Name = Name\n| extend Account_0_UPNSuffix = UPNSuffix\n| extend IP_0_Address = CallerIpAddress\n", + "version": 2, + "tags": [ { - "dataTypes": [ - "AzureActivity" - ], - "connectorId": "AzureActivity" - } - ], - "tactics": [ - "CredentialAccess", - "DefenseEvasion" - ], - "techniques": [ - "T1528", - "T1550" - ], - "entityMappings": [ + "name": "description", + "value": "Looks for administrative actions in AzureActivity from known VPS provider network ranges.\nThis is not an exhaustive list of VPS provider ranges but covers some of the most prevalent providers observed." + }, { - "entityType": "Account", - "fieldMappings": [ - { - "columnName": "Name", - "identifier": "Name" - }, - { - "columnName": "UPNSuffix", - "identifier": "UPNSuffix" - } - ] + "name": "tactics", + "value": "InitialAccess" }, { - "entityType": "IP", - "fieldMappings": [ - { - "columnName": "CallerIpAddress", - "identifier": "Address" - } - ] + "name": "techniques", + "value": "T1078" } ] } @@ -1990,13 +2196,13 @@ { "type": "Microsoft.OperationalInsights/workspaces/providers/metadata", "apiVersion": "2022-01-01-preview", - "name": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/',concat('AnalyticsRule-', last(split(variables('analyticRuleId3'),'/'))))]", + "name": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/',concat('HuntingQuery-', last(split(variables('huntingQueryId4'),'/'))))]", "properties": { - "description": "Azure Activity Analytics Rule 3", - "parentId": "[variables('analyticRuleId3')]", - "contentId": "[variables('_analyticRulecontentId3')]", - "kind": "AnalyticsRule", - "version": "[variables('analyticRuleVersion3')]", + "description": "Azure Activity Hunting Query 4", + "parentId": "[variables('huntingQueryId4')]", + "contentId": "[variables('_huntingQuerycontentId4')]", + "kind": "HuntingQuery", + "version": "[variables('huntingQueryVersion4')]", "source": { "kind": "Solution", "name": "Azure Activity", @@ -2015,102 +2221,59 @@ } } ] - } - } - }, - { - "type": "Microsoft.Resources/templateSpecs", - "apiVersion": "2022-02-01", - "name": "[variables('analyticRuleTemplateSpecName4')]", - "location": "[parameters('workspace-location')]", - "tags": { - "hidden-sentinelWorkspaceId": "[variables('workspaceResourceId')]", - "hidden-sentinelContentType": "AnalyticsRule" - }, - "properties": { - "description": "Azure Activity Analytics Rule 4 with template", - "displayName": "Azure Activity Analytics Rule template" + }, + "packageKind": "Solution", + "packageVersion": "[variables('_solutionVersion')]", + "packageName": "[variables('_solutionName')]", + "packageId": "[variables('_solutionId')]", + "contentSchemaVersion": "3.0.0", + "contentId": "[variables('_huntingQuerycontentId4')]", + "contentKind": "HuntingQuery", + "displayName": "AzureActivity Administration From VPS Providers", + "contentProductId": "[variables('_huntingQuerycontentProductId4')]", + "id": "[variables('_huntingQuerycontentProductId4')]", + "version": "[variables('huntingQueryVersion4')]" } }, { - "type": "Microsoft.Resources/templateSpecs/versions", - "apiVersion": "2022-02-01", - "name": "[concat(variables('analyticRuleTemplateSpecName4'),'/',variables('analyticRuleVersion4'))]", + "type": "Microsoft.OperationalInsights/workspaces/providers/contentTemplates", + "apiVersion": "2023-04-01-preview", + "name": "[variables('huntingQueryTemplateSpecName5')]", "location": "[parameters('workspace-location')]", - "tags": { - "hidden-sentinelWorkspaceId": "[variables('workspaceResourceId')]", - "hidden-sentinelContentType": "AnalyticsRule" - }, "dependsOn": [ - "[resourceId('Microsoft.Resources/templateSpecs', variables('analyticRuleTemplateSpecName4'))]" + "[extensionResourceId(resourceId('Microsoft.OperationalInsights/workspaces', parameters('workspace')), 'Microsoft.SecurityInsights/contentPackages', variables('_solutionId'))]" ], "properties": { - "description": "Creating_Anomalous_Number_Of_Resources_detection_AnalyticalRules Analytics Rule with template version 2.0.6", + "description": "AzureNSG_AdministrativeOperations_HuntingQueries Hunting Query with template version 3.0.0", "mainTemplate": { "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", - "contentVersion": "[variables('analyticRuleVersion4')]", + "contentVersion": "[variables('huntingQueryVersion5')]", "parameters": {}, "variables": {}, "resources": [ { - "type": "Microsoft.SecurityInsights/AlertRuleTemplates", - "name": "[variables('AnalyticRulecontentId4')]", - "apiVersion": "2022-04-01-preview", - "kind": "Scheduled", + "type": "Microsoft.OperationalInsights/savedSearches", + "apiVersion": "2022-10-01", + "name": "Azure_Activity_Hunting_Query_5", "location": "[parameters('workspace-location')]", "properties": { - "description": "Indicates when an anomalous number of VM creations or deployment activities occur in Azure via the AzureActivity log. This query generates the baseline pattern of cloud resource creation by an individual and generates an anomaly when any unusual spike is detected. These anomalies from unusual or privileged users could be an indication of a cloud infrastructure takedown by an adversary.", - "displayName": "Suspicious number of resource creation or deployment activities", - "enabled": false, - "query": "let szOperationNames = dynamic([\"microsoft.compute/virtualMachines/write\", \"microsoft.resources/deployments/write\"]);\nlet starttime = 7d;\nlet endtime = 1d;\nlet timeframe = 1d;\nlet TimeSeriesData =\nAzureActivity\n| where TimeGenerated between (startofday(ago(starttime)) .. startofday(now()))\n| where OperationNameValue in~ (szOperationNames)\n| project TimeGenerated, Caller \n| make-series Total = count() on TimeGenerated from startofday(ago(starttime)) to startofday(now()) step timeframe by Caller; \nTimeSeriesData\n| extend (anomalies, score, baseline) = series_decompose_anomalies(Total, 3, -1, 'linefit')\n| mv-expand Total to typeof(double), TimeGenerated to typeof(datetime), anomalies to typeof(double), score to typeof(double), baseline to typeof(long) \n| where TimeGenerated >= startofday(ago(endtime))\n| where anomalies > 0 and baseline > 0\n| project Caller, TimeGenerated, Total, baseline, anomalies, score\n| join (AzureActivity\n| where TimeGenerated > startofday(ago(endtime)) \n| where OperationNameValue in~ (szOperationNames)\n| summarize make_set(OperationNameValue,100), make_set(_ResourceId,100), make_set(CallerIpAddress,100) by bin(TimeGenerated, timeframe), Caller\n) on TimeGenerated, Caller\n| mv-expand CallerIpAddress=set_CallerIpAddress\n| project-away Caller1\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 '@',Caller,\"\")\n", - "queryFrequency": "P1D", - "queryPeriod": "P7D", - "severity": "Medium", - "suppressionDuration": "PT1H", - "suppressionEnabled": false, - "triggerOperator": "GreaterThan", - "triggerThreshold": 0, - "status": "Available", - "requiredDataConnectors": [ + "eTag": "*", + "displayName": "Azure Network Security Group NSG Administrative Operations", + "category": "Hunting Queries", + "query": "let opValues = dynamic([\"Microsoft.Network/networkSecurityGroups/write\", \"Microsoft.Network/networkSecurityGroups/delete\"]);\n// Azure NSG Create / Update / Delete\nAzureActivity\n| where Category =~ \"Administrative\"\n| where OperationNameValue in~ (opValues)\n| where ActivitySubstatusValue in~ (\"Created\", \"OK\",\"Accepted\")\n| sort by TimeGenerated desc\n| extend Name = tostring(split(Caller,'@',0)[0]), UPNSuffix = tostring(split(Caller,'@',1)[0])\n| extend Account_0_Name = Name\n| extend Account_0_UPNSuffix = UPNSuffix\n| extend IP_0_Address = CallerIpAddress\n", + "version": 2, + "tags": [ { - "dataTypes": [ - "AzureActivity" - ], - "connectorId": "AzureActivity" - } - ], - "tactics": [ - "Impact" - ], - "techniques": [ - "T1496" - ], - "entityMappings": [ + "name": "description", + "value": "Identifies a set of Azure NSG administrative and operational detection queries for hunting activities." + }, { - "entityType": "Account", - "fieldMappings": [ - { - "columnName": "Name", - "identifier": "Name" - }, - { - "columnName": "UPNSuffix", - "identifier": "UPNSuffix" - }, - { - "columnName": "AadUserId", - "identifier": "AadUserId" - } - ] + "name": "tactics", + "value": "Impact" }, { - "entityType": "IP", - "fieldMappings": [ - { - "columnName": "CallerIpAddress", - "identifier": "Address" - } - ] + "name": "techniques", + "value": "T1496" } ] } @@ -2118,13 +2281,13 @@ { "type": "Microsoft.OperationalInsights/workspaces/providers/metadata", "apiVersion": "2022-01-01-preview", - "name": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/',concat('AnalyticsRule-', last(split(variables('analyticRuleId4'),'/'))))]", + "name": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/',concat('HuntingQuery-', last(split(variables('huntingQueryId5'),'/'))))]", "properties": { - "description": "Azure Activity Analytics Rule 4", - "parentId": "[variables('analyticRuleId4')]", - "contentId": "[variables('_analyticRulecontentId4')]", - "kind": "AnalyticsRule", - "version": "[variables('analyticRuleVersion4')]", + "description": "Azure Activity Hunting Query 5", + "parentId": "[variables('huntingQueryId5')]", + "contentId": "[variables('_huntingQuerycontentId5')]", + "kind": "HuntingQuery", + "version": "[variables('huntingQueryVersion5')]", "source": { "kind": "Solution", "name": "Azure Activity", @@ -2143,98 +2306,59 @@ } } ] - } - } - }, - { - "type": "Microsoft.Resources/templateSpecs", - "apiVersion": "2022-02-01", - "name": "[variables('analyticRuleTemplateSpecName5')]", - "location": "[parameters('workspace-location')]", - "tags": { - "hidden-sentinelWorkspaceId": "[variables('workspaceResourceId')]", - "hidden-sentinelContentType": "AnalyticsRule" - }, - "properties": { - "description": "Azure Activity Analytics Rule 5 with template", - "displayName": "Azure Activity Analytics Rule template" + }, + "packageKind": "Solution", + "packageVersion": "[variables('_solutionVersion')]", + "packageName": "[variables('_solutionName')]", + "packageId": "[variables('_solutionId')]", + "contentSchemaVersion": "3.0.0", + "contentId": "[variables('_huntingQuerycontentId5')]", + "contentKind": "HuntingQuery", + "displayName": "Azure Network Security Group NSG Administrative Operations", + "contentProductId": "[variables('_huntingQuerycontentProductId5')]", + "id": "[variables('_huntingQuerycontentProductId5')]", + "version": "[variables('huntingQueryVersion5')]" } }, { - "type": "Microsoft.Resources/templateSpecs/versions", - "apiVersion": "2022-02-01", - "name": "[concat(variables('analyticRuleTemplateSpecName5'),'/',variables('analyticRuleVersion5'))]", + "type": "Microsoft.OperationalInsights/workspaces/providers/contentTemplates", + "apiVersion": "2023-04-01-preview", + "name": "[variables('huntingQueryTemplateSpecName6')]", "location": "[parameters('workspace-location')]", - "tags": { - "hidden-sentinelWorkspaceId": "[variables('workspaceResourceId')]", - "hidden-sentinelContentType": "AnalyticsRule" - }, "dependsOn": [ - "[resourceId('Microsoft.Resources/templateSpecs', variables('analyticRuleTemplateSpecName5'))]" + "[extensionResourceId(resourceId('Microsoft.OperationalInsights/workspaces', parameters('workspace')), 'Microsoft.SecurityInsights/contentPackages', variables('_solutionId'))]" ], "properties": { - "description": "Creation_of_Expensive_Computes_in_Azure_AnalyticalRules Analytics Rule with template version 2.0.6", + "description": "AzureRunCommandFromAzureIP_HuntingQueries Hunting Query with template version 3.0.0", "mainTemplate": { "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", - "contentVersion": "[variables('analyticRuleVersion5')]", + "contentVersion": "[variables('huntingQueryVersion6')]", "parameters": {}, "variables": {}, "resources": [ { - "type": "Microsoft.SecurityInsights/AlertRuleTemplates", - "name": "[variables('AnalyticRulecontentId5')]", - "apiVersion": "2022-04-01-preview", - "kind": "Scheduled", + "type": "Microsoft.OperationalInsights/savedSearches", + "apiVersion": "2022-10-01", + "name": "Azure_Activity_Hunting_Query_6", "location": "[parameters('workspace-location')]", "properties": { - "description": "Identifies the creation of large size or expensive VMs (with GPUs or with a large number of virtual CPUs) in Azure.\nAn adversary may create new or update existing virtual machines to evade defenses or use them for cryptomining purposes.\nFor Windows/Linux Vm Sizes, see https://docs.microsoft.com/azure/virtual-machines/windows/sizes \nAzure VM Naming Conventions, see https://docs.microsoft.com/azure/virtual-machines/vm-naming-conventions", - "displayName": "Creation of expensive computes in Azure", - "enabled": false, - "query": "let tokens = dynamic([\"416\",\"208\",\"192\",\"128\",\"120\",\"96\",\"80\",\"72\",\"64\",\"48\",\"44\",\"40\",\"g5\",\"gs5\",\"g4\",\"gs4\",\"nc12\",\"nc24\",\"nv24\"]);\nlet operationList = dynamic([\"microsoft.compute/virtualmachines/write\", \"microsoft.resources/deployments/write\"]);\nAzureActivity\n| where OperationNameValue in~ (operationList)\n| where ActivityStatusValue startswith \"Accept\"\n| where Properties has 'vmSize'\n| extend parsed_property= parse_json(tostring((parse_json(Properties).responseBody))).properties\n| extend vmSize = tostring((parsed_property.hardwareProfile).vmSize)\n| where vmSize has_any (tokens)\n| extend ComputerName = tostring((parsed_property.osProfile).computerName)\n| project TimeGenerated, OperationNameValue, ActivityStatusValue, Caller, CallerIpAddress, ComputerName, vmSize\n| extend Name = tostring(split(Caller,'@',0)[0]), UPNSuffix = tostring(split(Caller,'@',1)[0])\n", - "queryFrequency": "P1D", - "queryPeriod": "P1D", - "severity": "Low", - "suppressionDuration": "PT1H", - "suppressionEnabled": false, - "triggerOperator": "GreaterThan", - "triggerThreshold": 1, - "status": "Available", - "requiredDataConnectors": [ + "eTag": "*", + "displayName": "Azure VM Run Command executed from Azure IP address", + "category": "Hunting Queries", + "query": "let azure_ranges = externaldata(changeNumber: string, cloud: string, values: dynamic)\n[\"https://raw.githubusercontent.com/microsoft/mstic/master/PublicFeeds/MSFTIPRanges/ServiceTags_Public.json\"] with(format='multijson')\n| mv-expand values\n| extend Name = values.name, AddressPrefixes = values.properties.addressPrefixes\n| where Name startswith \"WindowsVirtualDesktop\"\n| mv-expand AddressPrefixes\n| summarize by tostring(AddressPrefixes);\nAzureActivity\n| where TimeGenerated > ago(30d)\n// Isolate run command actions\n| where OperationNameValue == \"Microsoft.Compute/virtualMachines/runCommand/action\"\n// Confirm that the operation impacted a virtual machine\n| where Authorization has \"virtualMachines\"\n// Each runcommand operation consists of three events when successful, Started, Accepted (or Rejected), Successful (or Failed).\n| summarize StartTime=min(TimeGenerated), EndTime=max(TimeGenerated), max(CallerIpAddress), make_list(ActivityStatusValue) by CorrelationId, Authorization, Caller\n// Limit to Run Command executions that Succeeded\n| where list_ActivityStatusValue has \"Succeeded\"\n// Extract data from the Authorization field, allowing us to later extract the Caller (UPN) and CallerIpAddress\n| extend Authorization_d = parse_json(Authorization)\n| extend Scope = Authorization_d.scope\n| extend Scope_s = split(Scope, \"/\")\n| extend Subscription = tostring(Scope_s[2])\n| extend VirtualMachineName = tostring(Scope_s[-1])\n| project StartTime, EndTime, Subscription, VirtualMachineName, CorrelationId, Caller, CallerIpAddress=max_CallerIpAddress\n| evaluate ipv4_lookup(azure_ranges, CallerIpAddress, AddressPrefixes)\n| extend IP_0_Address = CallerIpAddress\n", + "version": 2, + "tags": [ { - "dataTypes": [ - "AzureActivity" - ], - "connectorId": "AzureActivity" - } - ], - "tactics": [ - "DefenseEvasion" - ], - "techniques": [ - "T1578" - ], - "entityMappings": [ + "name": "description", + "value": "Identifies any Azure VM Run Command operation executed from an Azure IP address.\nRun Command allows an attacker or legitimate user to execute arbitrary PowerShell\non a target VM. This technique has been seen in use by NOBELIUM." + }, { - "entityType": "Account", - "fieldMappings": [ - { - "columnName": "Name", - "identifier": "Name" - }, - { - "columnName": "UPNSuffix", - "identifier": "UPNSuffix" - } - ] + "name": "tactics", + "value": "LateralMovement,CredentialAccess" }, { - "entityType": "IP", - "fieldMappings": [ - { - "columnName": "CallerIpAddress", - "identifier": "Address" - } - ] + "name": "techniques", + "value": "T1570,T1078.004" } ] } @@ -2242,13 +2366,13 @@ { "type": "Microsoft.OperationalInsights/workspaces/providers/metadata", "apiVersion": "2022-01-01-preview", - "name": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/',concat('AnalyticsRule-', last(split(variables('analyticRuleId5'),'/'))))]", + "name": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/',concat('HuntingQuery-', last(split(variables('huntingQueryId6'),'/'))))]", "properties": { - "description": "Azure Activity Analytics Rule 5", - "parentId": "[variables('analyticRuleId5')]", - "contentId": "[variables('_analyticRulecontentId5')]", - "kind": "AnalyticsRule", - "version": "[variables('analyticRuleVersion5')]", + "description": "Azure Activity Hunting Query 6", + "parentId": "[variables('huntingQueryId6')]", + "contentId": "[variables('_huntingQuerycontentId6')]", + "kind": "HuntingQuery", + "version": "[variables('huntingQueryVersion6')]", "source": { "kind": "Solution", "name": "Azure Activity", @@ -2267,106 +2391,59 @@ } } ] - } - } - }, - { - "type": "Microsoft.Resources/templateSpecs", - "apiVersion": "2022-02-01", - "name": "[variables('analyticRuleTemplateSpecName6')]", - "location": "[parameters('workspace-location')]", - "tags": { - "hidden-sentinelWorkspaceId": "[variables('workspaceResourceId')]", - "hidden-sentinelContentType": "AnalyticsRule" - }, - "properties": { - "description": "Azure Activity Analytics Rule 6 with template", - "displayName": "Azure Activity Analytics Rule template" + }, + "packageKind": "Solution", + "packageVersion": "[variables('_solutionVersion')]", + "packageName": "[variables('_solutionName')]", + "packageId": "[variables('_solutionId')]", + "contentSchemaVersion": "3.0.0", + "contentId": "[variables('_huntingQuerycontentId6')]", + "contentKind": "HuntingQuery", + "displayName": "Azure VM Run Command executed from Azure IP address", + "contentProductId": "[variables('_huntingQuerycontentProductId6')]", + "id": "[variables('_huntingQuerycontentProductId6')]", + "version": "[variables('huntingQueryVersion6')]" } }, { - "type": "Microsoft.Resources/templateSpecs/versions", - "apiVersion": "2022-02-01", - "name": "[concat(variables('analyticRuleTemplateSpecName6'),'/',variables('analyticRuleVersion6'))]", + "type": "Microsoft.OperationalInsights/workspaces/providers/contentTemplates", + "apiVersion": "2023-04-01-preview", + "name": "[variables('huntingQueryTemplateSpecName7')]", "location": "[parameters('workspace-location')]", - "tags": { - "hidden-sentinelWorkspaceId": "[variables('workspaceResourceId')]", - "hidden-sentinelContentType": "AnalyticsRule" - }, "dependsOn": [ - "[resourceId('Microsoft.Resources/templateSpecs', variables('analyticRuleTemplateSpecName6'))]" + "[extensionResourceId(resourceId('Microsoft.OperationalInsights/workspaces', parameters('workspace')), 'Microsoft.SecurityInsights/contentPackages', variables('_solutionId'))]" ], "properties": { - "description": "Granting_Permissions_To_Account_detection_AnalyticalRules Analytics Rule with template version 2.0.6", + "description": "AzureSentinelConnectors_AdministrativeOperations_HuntingQueries Hunting Query with template version 3.0.0", "mainTemplate": { "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", - "contentVersion": "[variables('analyticRuleVersion6')]", + "contentVersion": "[variables('huntingQueryVersion7')]", "parameters": {}, "variables": {}, "resources": [ { - "type": "Microsoft.SecurityInsights/AlertRuleTemplates", - "name": "[variables('AnalyticRulecontentId6')]", - "apiVersion": "2022-04-01-preview", - "kind": "Scheduled", + "type": "Microsoft.OperationalInsights/savedSearches", + "apiVersion": "2022-10-01", + "name": "Azure_Activity_Hunting_Query_7", "location": "[parameters('workspace-location')]", "properties": { - "description": "Identifies IPs from which users grant access to other users on Azure resources and alerts when a previously unseen source IP address is used.", - "displayName": "Suspicious granting of permissions to an account", - "enabled": false, - "query": "let starttime = 14d;\nlet endtime = 1d;\n// The number of operations above which an IP address is considered an unusual source of role assignment operations\nlet alertOperationThreshold = 5;\nlet AzureBuiltInRole = externaldata(Role:string,RoleDescription:string,ID:string) [@\"https://raw.githubusercontent.com/Azure/Azure-Sentinel/master/Sample%20Data/Feeds/AzureBuiltInRole.csv\"] with (format=\"csv\", ignoreFirstRecord=True);\nlet createRoleAssignmentActivity = AzureActivity\n| where OperationNameValue =~ \"microsoft.authorization/roleassignments/write\";\nlet RoleAssignedActivity = createRoleAssignmentActivity \n| where TimeGenerated between (ago(starttime) .. ago(endtime))\n| summarize count() by CallerIpAddress, Caller, bin(TimeGenerated, 1d)\n| where count_ >= alertOperationThreshold\n// Returns all the records from the right side that don't have matches from the left.\n| join kind = rightanti ( \ncreateRoleAssignmentActivity\n| where TimeGenerated > ago(endtime)\n| extend parsed_property = tostring(parse_json(Properties).requestbody)\n| extend PrincipalId = case(parsed_property has_cs 'PrincipalId',parse_json(parsed_property).Properties.PrincipalId, parsed_property has_cs 'principalId',parse_json(parsed_property).properties.principalId,\"\")\n| extend PrincipalType = case(parsed_property has_cs 'PrincipalType',parse_json(parsed_property).Properties.PrincipalType, parsed_property has_cs 'principalType',parse_json(parsed_property).properties.principalType, \"\")\n| extend Scope = case(parsed_property has_cs 'Scope',parse_json(parsed_property).Properties.Scope, parsed_property has_cs 'scope',parse_json(parsed_property).properties.scope,\"\")\n| extend RoleAddedDetails = case(parsed_property has_cs 'RoleDefinitionId',parse_json(parsed_property).Properties.RoleDefinitionId,parsed_property has_cs 'roleDefinitionId',parse_json(parsed_property).properties.roleDefinitionId,\"\")\n| summarize StartTimeUtc = min(TimeGenerated), EndTimeUtc = max(TimeGenerated), ActivityTimeStamp = make_set(TimeGenerated), ActivityStatusValue = make_set(ActivityStatusValue), CorrelationId = make_set(CorrelationId), ActivityCountByCallerIPAddress = count() \nby ResourceId, CallerIpAddress, Caller, OperationNameValue, Resource, ResourceGroup, PrincipalId, PrincipalType, Scope, RoleAddedDetails\n) on CallerIpAddress, Caller\n| extend timestamp = StartTimeUtc, AccountCustomEntity = Caller, IPCustomEntity = CallerIpAddress;\nlet RoleAssignedActivitywithRoleDetails = RoleAssignedActivity\n| extend RoleAssignedID = tostring(split(RoleAddedDetails, \"/\")[-1])\n// Returns all matching records from left and right sides.\n| join kind = inner (AzureBuiltInRole \n) on $left.RoleAssignedID == $right.ID;\nlet CallerIPCountSummary = RoleAssignedActivitywithRoleDetails | summarize AssignmentCountbyCaller = count() by Caller, CallerIpAddress;\nlet RoleAssignedActivityWithCount = RoleAssignedActivitywithRoleDetails | join kind = inner (CallerIPCountSummary | project Caller, AssignmentCountbyCaller, CallerIpAddress) on Caller, CallerIpAddress;\nRoleAssignedActivityWithCount\n| summarize arg_max(StartTimeUtc, *) by PrincipalId, RoleAssignedID\n// \tReturns all the records from the left side and only matching records from the right side.\n| join kind = leftouter( IdentityInfo\n| summarize arg_max(TimeGenerated, *) by AccountObjectId\n) on $left.PrincipalId == $right.AccountObjectId\n// Check if assignment count is greater than the threshold.\n| where AssignmentCountbyCaller >= alertOperationThreshold\n| project ActivityTimeStamp, OperationNameValue, Caller, CallerIpAddress, PrincipalId, RoleAssignedID, RoleAddedDetails, Role, RoleDescription, AccountUPN, AccountCreationTime, GroupMembership, UserType, ActivityStatusValue, ResourceGroup, PrincipalType, Scope, CorrelationId, timestamp, AccountCustomEntity, IPCustomEntity, AssignmentCountbyCaller\n| extend Name = tostring(split(Caller,'@',0)[0]), UPNSuffix = tostring(split(Caller,'@',1)[0])\n", - "queryFrequency": "P1D", - "queryPeriod": "P14D", - "severity": "Medium", - "suppressionDuration": "PT1H", - "suppressionEnabled": false, - "triggerOperator": "GreaterThan", - "triggerThreshold": 0, - "status": "Available", - "requiredDataConnectors": [ + "eTag": "*", + "displayName": "Microsoft Sentinel Connectors Administrative Operations", + "category": "Hunting Queries", + "query": "let opValues = dynamic([\"Microsoft.SecurityInsights/dataConnectors/write\", \"Microsoft.SecurityInsights/dataConnectors/delete\"]);\n// Microsoft Sentinel Data Connectors Update / Delete\nAzureActivity\n| where OperationNameValue in~ (opValues)\n| where ActivitySubstatusValue in~ (\"Created\", \"OK\")\n| sort by TimeGenerated desc\n| extend Name = tostring(split(Caller,'@',0)[0]), UPNSuffix = tostring(split(Caller,'@',1)[0])\n| extend Account_0_Name = Name\n| extend Account_0_UPNSuffix = UPNSuffix\n| extend IP_0_Address = CallerIpAddress\n", + "version": 2, + "tags": [ { - "dataTypes": [ - "AzureActivity" - ], - "connectorId": "AzureActivity" + "name": "description", + "value": "Identifies a set of Microsoft Sentinel Data Connectors for administrative and operational detection queries for hunting activities." }, { - "dataTypes": [ - "IdentityInfo" - ], - "connectorId": "BehaviorAnalytics" - } - ], - "tactics": [ - "Persistence", - "PrivilegeEscalation" - ], - "techniques": [ - "T1098", - "T1548" - ], - "entityMappings": [ - { - "entityType": "Account", - "fieldMappings": [ - { - "columnName": "Name", - "identifier": "Name" - }, - { - "columnName": "UPNSuffix", - "identifier": "UPNSuffix" - } - ] + "name": "tactics", + "value": "Impact" }, { - "entityType": "IP", - "fieldMappings": [ - { - "columnName": "CallerIpAddress", - "identifier": "Address" - } - ] + "name": "techniques", + "value": "T1496" } ] } @@ -2374,13 +2451,13 @@ { "type": "Microsoft.OperationalInsights/workspaces/providers/metadata", "apiVersion": "2022-01-01-preview", - "name": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/',concat('AnalyticsRule-', last(split(variables('analyticRuleId6'),'/'))))]", + "name": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/',concat('HuntingQuery-', last(split(variables('huntingQueryId7'),'/'))))]", "properties": { - "description": "Azure Activity Analytics Rule 6", - "parentId": "[variables('analyticRuleId6')]", - "contentId": "[variables('_analyticRulecontentId6')]", - "kind": "AnalyticsRule", - "version": "[variables('analyticRuleVersion6')]", + "description": "Azure Activity Hunting Query 7", + "parentId": "[variables('huntingQueryId7')]", + "contentId": "[variables('_huntingQuerycontentId7')]", + "kind": "HuntingQuery", + "version": "[variables('huntingQueryVersion7')]", "source": { "kind": "Solution", "name": "Azure Activity", @@ -2399,94 +2476,59 @@ } } ] - } - } - }, - { - "type": "Microsoft.Resources/templateSpecs", - "apiVersion": "2022-02-01", - "name": "[variables('analyticRuleTemplateSpecName7')]", - "location": "[parameters('workspace-location')]", - "tags": { - "hidden-sentinelWorkspaceId": "[variables('workspaceResourceId')]", - "hidden-sentinelContentType": "AnalyticsRule" - }, - "properties": { - "description": "Azure Activity Analytics Rule 7 with template", - "displayName": "Azure Activity Analytics Rule template" + }, + "packageKind": "Solution", + "packageVersion": "[variables('_solutionVersion')]", + "packageName": "[variables('_solutionName')]", + "packageId": "[variables('_solutionId')]", + "contentSchemaVersion": "3.0.0", + "contentId": "[variables('_huntingQuerycontentId7')]", + "contentKind": "HuntingQuery", + "displayName": "Microsoft Sentinel Connectors Administrative Operations", + "contentProductId": "[variables('_huntingQuerycontentProductId7')]", + "id": "[variables('_huntingQuerycontentProductId7')]", + "version": "[variables('huntingQueryVersion7')]" } }, { - "type": "Microsoft.Resources/templateSpecs/versions", - "apiVersion": "2022-02-01", - "name": "[concat(variables('analyticRuleTemplateSpecName7'),'/',variables('analyticRuleVersion7'))]", + "type": "Microsoft.OperationalInsights/workspaces/providers/contentTemplates", + "apiVersion": "2023-04-01-preview", + "name": "[variables('huntingQueryTemplateSpecName8')]", "location": "[parameters('workspace-location')]", - "tags": { - "hidden-sentinelWorkspaceId": "[variables('workspaceResourceId')]", - "hidden-sentinelContentType": "AnalyticsRule" - }, "dependsOn": [ - "[resourceId('Microsoft.Resources/templateSpecs', variables('analyticRuleTemplateSpecName7'))]" + "[extensionResourceId(resourceId('Microsoft.OperationalInsights/workspaces', parameters('workspace')), 'Microsoft.SecurityInsights/contentPackages', variables('_solutionId'))]" ], "properties": { - "description": "NRT-AADHybridHealthADFSNewServer_AnalyticalRules Analytics Rule with template version 2.0.6", + "description": "AzureSentinelWorkbooks_AdministrativeOperation_HuntingQueries Hunting Query with template version 3.0.0", "mainTemplate": { "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", - "contentVersion": "[variables('analyticRuleVersion7')]", + "contentVersion": "[variables('huntingQueryVersion8')]", "parameters": {}, "variables": {}, "resources": [ { - "type": "Microsoft.SecurityInsights/AlertRuleTemplates", - "name": "[variables('AnalyticRulecontentId7')]", - "apiVersion": "2022-04-01-preview", - "kind": "NRT", + "type": "Microsoft.OperationalInsights/savedSearches", + "apiVersion": "2022-10-01", + "name": "Azure_Activity_Hunting_Query_8", "location": "[parameters('workspace-location')]", "properties": { - "description": "This detection uses AzureActivity logs (Administrative category) to identify the creation or update of a server instance in an Azure AD Hybrid Health AD FS service.\nA threat actor can create a new AD Health ADFS service and create a fake server instance to spoof AD FS signing logs. There is no need to compromise an on-premises AD FS server.\nThis can be done programmatically via HTTP requests to Azure. More information in this blog: https://o365blog.com/post/hybridhealthagent/", - "displayName": "NRT Azure Active Directory Hybrid Health AD FS New Server", - "enabled": false, - "query": "AzureActivity\n| where CategoryValue =~ 'Administrative'\n| where ResourceProviderValue =~ 'Microsoft.ADHybridHealthService'\n| where _ResourceId has 'AdFederationService'\n| where OperationNameValue =~ 'Microsoft.ADHybridHealthService/services/servicemembers/action'\n| extend claimsJson = parse_json(Claims)\n| extend AppId = tostring(claimsJson.appid), AccountName = tostring(claimsJson.name), Name = tostring(split(Caller,'@',0)[0]), UPNSuffix = tostring(split(Caller,'@',1)[0])\n| project-away claimsJson\n", - "severity": "Medium", - "suppressionDuration": "PT1H", - "suppressionEnabled": false, - "status": "Available", - "requiredDataConnectors": [ + "eTag": "*", + "displayName": "Microsoft Sentinel Workbooks Administrative Operations", + "category": "Hunting Queries", + "query": "let opValues = dynamic([\"microsoft.insights/workbooks/write\", \"microsoft.insights/workbooks/delete\"]);\n// Microsoft Sentinel Workbook Create / Update / Delete\nAzureActivity\n| where Category =~ \"Administrative\"\n| where OperationNameValue in~ (opValues)\n| where ActivitySubstatusValue in~ (\"Created\", \"OK\")\n| sort by TimeGenerated desc\n| extend Name = tostring(split(Caller,'@',0)[0]), UPNSuffix = tostring(split(Caller,'@',1)[0])\n| extend Account_0_Name = Name\n| extend Account_0_UPNSuffix = UPNSuffix\n| extend IP_0_Address = CallerIpAddress\n", + "version": 2, + "tags": [ { - "dataTypes": [ - "AzureActivity" - ], - "connectorId": "AzureActivity" - } - ], - "tactics": [ - "DefenseEvasion" - ], - "techniques": [ - "T1578" - ], - "entityMappings": [ + "name": "description", + "value": "Identifies set of Microsoft Sentinel Workbooks administrative operational detection queries for hunting activites" + }, { - "entityType": "Account", - "fieldMappings": [ - { - "columnName": "Name", - "identifier": "Name" - }, - { - "columnName": "UPNSuffix", - "identifier": "UPNSuffix" - } - ] + "name": "tactics", + "value": "Impact" }, { - "entityType": "IP", - "fieldMappings": [ - { - "columnName": "CallerIpAddress", - "identifier": "Address" - } - ] + "name": "techniques", + "value": "T1496" } ] } @@ -2494,13 +2536,13 @@ { "type": "Microsoft.OperationalInsights/workspaces/providers/metadata", "apiVersion": "2022-01-01-preview", - "name": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/',concat('AnalyticsRule-', last(split(variables('analyticRuleId7'),'/'))))]", + "name": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/',concat('HuntingQuery-', last(split(variables('huntingQueryId8'),'/'))))]", "properties": { - "description": "Azure Activity Analytics Rule 7", - "parentId": "[variables('analyticRuleId7')]", - "contentId": "[variables('_analyticRulecontentId7')]", - "kind": "AnalyticsRule", - "version": "[variables('analyticRuleVersion7')]", + "description": "Azure Activity Hunting Query 8", + "parentId": "[variables('huntingQueryId8')]", + "contentId": "[variables('_huntingQuerycontentId8')]", + "kind": "HuntingQuery", + "version": "[variables('huntingQueryVersion8')]", "source": { "kind": "Solution", "name": "Azure Activity", @@ -2519,94 +2561,59 @@ } } ] - } - } - }, - { - "type": "Microsoft.Resources/templateSpecs", - "apiVersion": "2022-02-01", - "name": "[variables('analyticRuleTemplateSpecName8')]", - "location": "[parameters('workspace-location')]", - "tags": { - "hidden-sentinelWorkspaceId": "[variables('workspaceResourceId')]", - "hidden-sentinelContentType": "AnalyticsRule" - }, - "properties": { - "description": "Azure Activity Analytics Rule 8 with template", - "displayName": "Azure Activity Analytics Rule template" + }, + "packageKind": "Solution", + "packageVersion": "[variables('_solutionVersion')]", + "packageName": "[variables('_solutionName')]", + "packageId": "[variables('_solutionId')]", + "contentSchemaVersion": "3.0.0", + "contentId": "[variables('_huntingQuerycontentId8')]", + "contentKind": "HuntingQuery", + "displayName": "Microsoft Sentinel Workbooks Administrative Operations", + "contentProductId": "[variables('_huntingQuerycontentProductId8')]", + "id": "[variables('_huntingQuerycontentProductId8')]", + "version": "[variables('huntingQueryVersion8')]" } }, { - "type": "Microsoft.Resources/templateSpecs/versions", - "apiVersion": "2022-02-01", - "name": "[concat(variables('analyticRuleTemplateSpecName8'),'/',variables('analyticRuleVersion8'))]", + "type": "Microsoft.OperationalInsights/workspaces/providers/contentTemplates", + "apiVersion": "2023-04-01-preview", + "name": "[variables('huntingQueryTemplateSpecName9')]", "location": "[parameters('workspace-location')]", - "tags": { - "hidden-sentinelWorkspaceId": "[variables('workspaceResourceId')]", - "hidden-sentinelContentType": "AnalyticsRule" - }, "dependsOn": [ - "[resourceId('Microsoft.Resources/templateSpecs', variables('analyticRuleTemplateSpecName8'))]" + "[extensionResourceId(resourceId('Microsoft.OperationalInsights/workspaces', parameters('workspace')), 'Microsoft.SecurityInsights/contentPackages', variables('_solutionId'))]" ], "properties": { - "description": "NRT_Creation_of_Expensive_Computes_in_Azure_AnalyticalRules Analytics Rule with template version 2.0.6", + "description": "AzureVirtualNetworkSubnets_AdministrativeOperationset_HuntingQueries Hunting Query with template version 3.0.0", "mainTemplate": { "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", - "contentVersion": "[variables('analyticRuleVersion8')]", + "contentVersion": "[variables('huntingQueryVersion9')]", "parameters": {}, "variables": {}, "resources": [ { - "type": "Microsoft.SecurityInsights/AlertRuleTemplates", - "name": "[variables('AnalyticRulecontentId8')]", - "apiVersion": "2022-04-01-preview", - "kind": "NRT", + "type": "Microsoft.OperationalInsights/savedSearches", + "apiVersion": "2022-10-01", + "name": "Azure_Activity_Hunting_Query_9", "location": "[parameters('workspace-location')]", "properties": { - "description": "Identifies the creation of large size or expensive VMs (with GPUs or with a large number of virtual CPUs) in Azure.\nAn adversary may create new or update existing virtual machines to evade defenses or use them for cryptomining purposes.\nFor Windows/Linux Vm Sizes, see https://docs.microsoft.com/azure/virtual-machines/windows/sizes \nAzure VM Naming Conventions, see https://docs.microsoft.com/azure/virtual-machines/vm-naming-conventions", - "displayName": "NRT Creation of expensive computes in Azure", - "enabled": false, - "query": "let tokens = dynamic([\"416\",\"208\",\"192\",\"128\",\"120\",\"96\",\"80\",\"72\",\"64\",\"48\",\"44\",\"40\",\"g5\",\"gs5\",\"g4\",\"gs4\",\"nc12\",\"nc24\",\"nv24\"]);\nlet operationList = dynamic([\"microsoft.compute/virtualmachines/write\", \"microsoft.resources/deployments/write\"]);\nAzureActivity\n| where OperationNameValue in~ (operationList)\n| where ActivityStatusValue startswith \"Accept\"\n| where Properties has 'vmSize'\n| extend parsed_property= parse_json(tostring((parse_json(Properties).responseBody))).properties\n| extend vmSize = tostring((parsed_property.hardwareProfile).vmSize)\n| where vmSize has_any (tokens)\n| extend ComputerName = tostring((parsed_property.osProfile).computerName)\n| project TimeGenerated, OperationNameValue, ActivityStatusValue, Caller, CallerIpAddress, ComputerName, vmSize\n| extend Name = tostring(split(Caller,'@',0)[0]), UPNSuffix = tostring(split(Caller,'@',1)[0])\n", - "severity": "Medium", - "suppressionDuration": "PT1H", - "suppressionEnabled": false, - "status": "Available", - "requiredDataConnectors": [ + "eTag": "*", + "displayName": "Azure Virtual Network Subnets Administrative Operations", + "category": "Hunting Queries", + "query": "let opValues = dynamic([\"Microsoft.Network/virtualNetworks/subnets/write\",\"Microsoft.Network/virtualNetworks/subnets/delete\"]);\n// Creating, Updating or Deleting Virtual Network Subnets\nAzureActivity\n| where CategoryValue =~ \"Administrative\"\n| where OperationNameValue in~ (opValues)\n| where ActivitySubstatusValue in~ (\"Created\",\"Accepted\")\n| sort by TimeGenerated desc\n| extend Name = tostring(split(Caller,'@',0)[0]), UPNSuffix = tostring(split(Caller,'@',1)[0])\n| extend Account_0_Name = Name\n| extend Account_0_UPNSuffix = UPNSuffix\n| extend IP_0_Address = CallerIpAddress\n", + "version": 2, + "tags": [ { - "dataTypes": [ - "AzureActivity" - ], - "connectorId": "AzureActivity" - } - ], - "tactics": [ - "DefenseEvasion" - ], - "techniques": [ - "T1578" - ], - "entityMappings": [ + "name": "description", + "value": "Identifies a set of Azure Virtual Network Subnets for administrative and operational detection queries for hunting activities." + }, { - "entityType": "Account", - "fieldMappings": [ - { - "columnName": "Name", - "identifier": "Name" - }, - { - "columnName": "UPNSuffix", - "identifier": "UPNSuffix" - } - ] + "name": "tactics", + "value": "Impact" }, { - "entityType": "IP", - "fieldMappings": [ - { - "columnName": "CallerIpAddress", - "identifier": "Address" - } - ] + "name": "techniques", + "value": "T1496" } ] } @@ -2614,13 +2621,13 @@ { "type": "Microsoft.OperationalInsights/workspaces/providers/metadata", "apiVersion": "2022-01-01-preview", - "name": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/',concat('AnalyticsRule-', last(split(variables('analyticRuleId8'),'/'))))]", + "name": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/',concat('HuntingQuery-', last(split(variables('huntingQueryId9'),'/'))))]", "properties": { - "description": "Azure Activity Analytics Rule 8", - "parentId": "[variables('analyticRuleId8')]", - "contentId": "[variables('_analyticRulecontentId8')]", - "kind": "AnalyticsRule", - "version": "[variables('analyticRuleVersion8')]", + "description": "Azure Activity Hunting Query 9", + "parentId": "[variables('huntingQueryId9')]", + "contentId": "[variables('_huntingQuerycontentId9')]", + "kind": "HuntingQuery", + "version": "[variables('huntingQueryVersion9')]", "source": { "kind": "Solution", "name": "Azure Activity", @@ -2639,98 +2646,59 @@ } } ] - } - } - }, - { - "type": "Microsoft.Resources/templateSpecs", - "apiVersion": "2022-02-01", - "name": "[variables('analyticRuleTemplateSpecName9')]", - "location": "[parameters('workspace-location')]", - "tags": { - "hidden-sentinelWorkspaceId": "[variables('workspaceResourceId')]", - "hidden-sentinelContentType": "AnalyticsRule" - }, - "properties": { - "description": "Azure Activity Analytics Rule 9 with template", - "displayName": "Azure Activity Analytics Rule template" + }, + "packageKind": "Solution", + "packageVersion": "[variables('_solutionVersion')]", + "packageName": "[variables('_solutionName')]", + "packageId": "[variables('_solutionId')]", + "contentSchemaVersion": "3.0.0", + "contentId": "[variables('_huntingQuerycontentId9')]", + "contentKind": "HuntingQuery", + "displayName": "Azure Virtual Network Subnets Administrative Operations", + "contentProductId": "[variables('_huntingQuerycontentProductId9')]", + "id": "[variables('_huntingQuerycontentProductId9')]", + "version": "[variables('huntingQueryVersion9')]" } }, { - "type": "Microsoft.Resources/templateSpecs/versions", - "apiVersion": "2022-02-01", - "name": "[concat(variables('analyticRuleTemplateSpecName9'),'/',variables('analyticRuleVersion9'))]", + "type": "Microsoft.OperationalInsights/workspaces/providers/contentTemplates", + "apiVersion": "2023-04-01-preview", + "name": "[variables('huntingQueryTemplateSpecName10')]", "location": "[parameters('workspace-location')]", - "tags": { - "hidden-sentinelWorkspaceId": "[variables('workspaceResourceId')]", - "hidden-sentinelContentType": "AnalyticsRule" - }, "dependsOn": [ - "[resourceId('Microsoft.Resources/templateSpecs', variables('analyticRuleTemplateSpecName9'))]" + "[extensionResourceId(resourceId('Microsoft.OperationalInsights/workspaces', parameters('workspace')), 'Microsoft.SecurityInsights/contentPackages', variables('_solutionId'))]" ], "properties": { - "description": "New-CloudShell-User_AnalyticalRules Analytics Rule with template version 2.0.6", + "description": "Common_Deployed_Resources_HuntingQueries Hunting Query with template version 3.0.0", "mainTemplate": { "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", - "contentVersion": "[variables('analyticRuleVersion9')]", + "contentVersion": "[variables('huntingQueryVersion10')]", "parameters": {}, "variables": {}, "resources": [ { - "type": "Microsoft.SecurityInsights/AlertRuleTemplates", - "name": "[variables('AnalyticRulecontentId9')]", - "apiVersion": "2022-04-01-preview", - "kind": "Scheduled", + "type": "Microsoft.OperationalInsights/savedSearches", + "apiVersion": "2022-10-01", + "name": "Azure_Activity_Hunting_Query_10", "location": "[parameters('workspace-location')]", "properties": { - "description": "Identifies when a user creates an Azure CloudShell for the first time.\nMonitor this activity to ensure only the expected users are using CloudShell.", - "displayName": "New CloudShell User", - "enabled": false, - "query": "let match_window = 3m;\nAzureActivity\n| where ResourceGroup has \"cloud-shell\"\n| where (OperationNameValue =~ \"Microsoft.Storage/storageAccounts/listKeys/action\")\n| where ActivityStatusValue =~ \"Success\"\n| extend TimeKey = bin(TimeGenerated, match_window), AzureIP = CallerIpAddress\n| join kind = inner\n(AzureActivity\n| where ResourceGroup has \"cloud-shell\"\n| where (OperationNameValue =~ \"Microsoft.Storage/storageAccounts/write\")\n| extend TimeKey = bin(TimeGenerated, match_window), UserIP = CallerIpAddress\n) on Caller, TimeKey\n| summarize count() by TimeKey, Caller, ResourceGroup, SubscriptionId, TenantId, AzureIP, UserIP, HTTPRequest, Type, Properties, CategoryValue, OperationList = strcat(OperationNameValue, ' , ', OperationNameValue1)\n| extend Name = tostring(split(Caller,'@',0)[0]), UPNSuffix = tostring(split(Caller,'@',1)[0])\n", - "queryFrequency": "P1D", - "queryPeriod": "P1D", - "severity": "Low", - "suppressionDuration": "PT1H", - "suppressionEnabled": false, - "triggerOperator": "GreaterThan", - "triggerThreshold": 0, - "status": "Available", - "requiredDataConnectors": [ + "eTag": "*", + "displayName": "Common deployed resources", + "category": "Hunting Queries", + "query": "AzureActivity\n| where OperationNameValue has_any (@\"deployments/write\", @\"virtualMachines/write\") \n| where ActivityStatusValue =~ \"Succeeded\"\n| summarize by bin(TimeGenerated,1d), Resource, ResourceGroup, ResourceId, OperationNameValue, Caller\n| evaluate basket()\n| where isnotempty(Caller) and isnotempty(Resource) and isnotempty(TimeGenerated)\n| order by Percent desc, TimeGenerated desc\n| extend Name = tostring(split(Caller,'@',0)[0]), UPNSuffix = tostring(split(Caller,'@',1)[0])\n| extend Account_0_Name = Name\n| extend Account_0_UPNSuffix = UPNSuffix\n| extend AzureResource_0_ResourceId = ResourceId\n// remove comments below on filters if the goal is to see more common or more rare Resource, Resource Group and Caller combinations\n//| where Percent <= 40 // <-- more rare\n//| where Percent >= 60 // <-- more common\n", + "version": 2, + "tags": [ { - "dataTypes": [ - "AzureActivity" - ], - "connectorId": "AzureActivity" - } - ], - "tactics": [ - "Execution" - ], - "techniques": [ - "T1059" - ], - "entityMappings": [ + "name": "description", + "value": "This query identifies common deployed resources in Azure, like resource names and groups. It can be used with other suspicious deployment signals to evaluate if a resource is commonly deployed or unique." + }, { - "entityType": "Account", - "fieldMappings": [ - { - "columnName": "Name", - "identifier": "Name" - }, - { - "columnName": "UPNSuffix", - "identifier": "UPNSuffix" - } - ] + "name": "tactics", + "value": "Impact" }, { - "entityType": "IP", - "fieldMappings": [ - { - "columnName": "UserIP", - "identifier": "Address" - } - ] + "name": "techniques", + "value": "T1496" } ] } @@ -2738,13 +2706,13 @@ { "type": "Microsoft.OperationalInsights/workspaces/providers/metadata", "apiVersion": "2022-01-01-preview", - "name": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/',concat('AnalyticsRule-', last(split(variables('analyticRuleId9'),'/'))))]", + "name": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/',concat('HuntingQuery-', last(split(variables('huntingQueryId10'),'/'))))]", "properties": { - "description": "Azure Activity Analytics Rule 9", - "parentId": "[variables('analyticRuleId9')]", - "contentId": "[variables('_analyticRulecontentId9')]", - "kind": "AnalyticsRule", - "version": "[variables('analyticRuleVersion9')]", + "description": "Azure Activity Hunting Query 10", + "parentId": "[variables('huntingQueryId10')]", + "contentId": "[variables('_huntingQuerycontentId10')]", + "kind": "HuntingQuery", + "version": "[variables('huntingQueryVersion10')]", "source": { "kind": "Solution", "name": "Azure Activity", @@ -2763,102 +2731,59 @@ } } ] - } - } - }, - { - "type": "Microsoft.Resources/templateSpecs", - "apiVersion": "2022-02-01", - "name": "[variables('analyticRuleTemplateSpecName10')]", - "location": "[parameters('workspace-location')]", - "tags": { - "hidden-sentinelWorkspaceId": "[variables('workspaceResourceId')]", - "hidden-sentinelContentType": "AnalyticsRule" - }, - "properties": { - "description": "Azure Activity Analytics Rule 10 with template", - "displayName": "Azure Activity Analytics Rule template" + }, + "packageKind": "Solution", + "packageVersion": "[variables('_solutionVersion')]", + "packageName": "[variables('_solutionName')]", + "packageId": "[variables('_solutionId')]", + "contentSchemaVersion": "3.0.0", + "contentId": "[variables('_huntingQuerycontentId10')]", + "contentKind": "HuntingQuery", + "displayName": "Common deployed resources", + "contentProductId": "[variables('_huntingQuerycontentProductId10')]", + "id": "[variables('_huntingQuerycontentProductId10')]", + "version": "[variables('huntingQueryVersion10')]" } }, { - "type": "Microsoft.Resources/templateSpecs/versions", - "apiVersion": "2022-02-01", - "name": "[concat(variables('analyticRuleTemplateSpecName10'),'/',variables('analyticRuleVersion10'))]", + "type": "Microsoft.OperationalInsights/workspaces/providers/contentTemplates", + "apiVersion": "2023-04-01-preview", + "name": "[variables('huntingQueryTemplateSpecName11')]", "location": "[parameters('workspace-location')]", - "tags": { - "hidden-sentinelWorkspaceId": "[variables('workspaceResourceId')]", - "hidden-sentinelContentType": "AnalyticsRule" - }, "dependsOn": [ - "[resourceId('Microsoft.Resources/templateSpecs', variables('analyticRuleTemplateSpecName10'))]" + "[extensionResourceId(resourceId('Microsoft.OperationalInsights/workspaces', parameters('workspace')), 'Microsoft.SecurityInsights/contentPackages', variables('_solutionId'))]" ], "properties": { - "description": "NewResourceGroupsDeployedTo_AnalyticalRules Analytics Rule with template version 2.0.6", + "description": "Creating_Anomalous_Number_Of_Resources_HuntingQueries Hunting Query with template version 3.0.0", "mainTemplate": { "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", - "contentVersion": "[variables('analyticRuleVersion10')]", + "contentVersion": "[variables('huntingQueryVersion11')]", "parameters": {}, "variables": {}, "resources": [ { - "type": "Microsoft.SecurityInsights/AlertRuleTemplates", - "name": "[variables('AnalyticRulecontentId10')]", - "apiVersion": "2022-04-01-preview", - "kind": "Scheduled", + "type": "Microsoft.OperationalInsights/savedSearches", + "apiVersion": "2022-10-01", + "name": "Azure_Activity_Hunting_Query_11", "location": "[parameters('workspace-location')]", "properties": { - "description": "Identifies when a rare Resource and ResourceGroup deployment occurs by a previously unseen caller.", - "displayName": "Suspicious Resource deployment", - "enabled": false, - "query": "// Add or remove operation names below as per your requirements. For operations lists, please refer to https://learn.microsoft.com/en-us/Azure/role-based-access-control/resource-provider-operations#all\nlet szOperationNames = dynamic([\"Microsoft.Compute/virtualMachines/write\", \"Microsoft.Resources/deployments/write\", \"Microsoft.Resources/subscriptions/resourceGroups/write\"]);\nlet starttime = 14d;\nlet endtime = 1d;\nlet RareCaller = AzureActivity\n| where TimeGenerated between (ago(starttime) .. ago(endtime))\n| where OperationNameValue in~ (szOperationNames)\n| summarize count() by CallerIpAddress, Caller, OperationNameValue, bin(TimeGenerated,1d)\n// Returns all the records from the right side that don't have matches from the left.\n| join kind=rightantisemi (\nAzureActivity\n| where TimeGenerated > ago(endtime)\n| where OperationNameValue in~ (szOperationNames)\n| summarize StartTimeUtc = min(TimeGenerated), EndTimeUtc = max(TimeGenerated), ActivityTimeStamp = make_set(TimeGenerated,100), ActivityStatusValue = make_set(ActivityStatusValue,100), CorrelationIds = make_set(CorrelationId,100), ResourceGroups = make_set(ResourceGroup,100), ResourceIds = make_set(_ResourceId,100), ActivityCountByCallerIPAddress = count()\nby CallerIpAddress, Caller, OperationNameValue) on CallerIpAddress, Caller, OperationNameValue;\nRareCaller\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 '@',Caller,\"\")\n", - "queryFrequency": "P1D", - "queryPeriod": "P14D", - "severity": "Low", - "suppressionDuration": "PT1H", - "suppressionEnabled": false, - "triggerOperator": "GreaterThan", - "triggerThreshold": 0, - "status": "Available", - "requiredDataConnectors": [ + "eTag": "*", + "displayName": "Creation of an anomalous number of resources", + "category": "Hunting Queries", + "query": "AzureActivity\n| where OperationNameValue in~ (\"microsoft.compute/virtualMachines/write\", \"microsoft.resources/deployments/write\")\n| where ActivityStatusValue == \"Succeeded\" \n| make-series dcount(ResourceId) default=0 on EventSubmissionTimestamp in range(ago(7d), now(), 1d) by Caller\n| extend Name = tostring(split(Caller,'@',0)[0]), UPNSuffix = tostring(split(Caller,'@',1)[0])\n| extend Account_0_Name = Name\n| extend Account_0_UPNSuffix = UPNSuffix\n", + "version": 2, + "tags": [ { - "dataTypes": [ - "AzureActivity" - ], - "connectorId": "AzureActivity" - } - ], - "tactics": [ - "Impact" - ], - "techniques": [ - "T1496" - ], - "entityMappings": [ + "name": "description", + "value": "Looks for anomalous number of resources creation or deployment activities in azure activity log.\nIt is best to run this query on a look back period which is at least 7 days." + }, { - "entityType": "Account", - "fieldMappings": [ - { - "columnName": "Name", - "identifier": "Name" - }, - { - "columnName": "UPNSuffix", - "identifier": "UPNSuffix" - }, - { - "columnName": "AadUserId", - "identifier": "AadUserId" - } - ] + "name": "tactics", + "value": "Impact" }, { - "entityType": "IP", - "fieldMappings": [ - { - "columnName": "CallerIpAddress", - "identifier": "Address" - } - ] + "name": "techniques", + "value": "T1496" } ] } @@ -2866,13 +2791,13 @@ { "type": "Microsoft.OperationalInsights/workspaces/providers/metadata", "apiVersion": "2022-01-01-preview", - "name": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/',concat('AnalyticsRule-', last(split(variables('analyticRuleId10'),'/'))))]", + "name": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/',concat('HuntingQuery-', last(split(variables('huntingQueryId11'),'/'))))]", "properties": { - "description": "Azure Activity Analytics Rule 10", - "parentId": "[variables('analyticRuleId10')]", - "contentId": "[variables('_analyticRulecontentId10')]", - "kind": "AnalyticsRule", - "version": "[variables('analyticRuleVersion10')]", + "description": "Azure Activity Hunting Query 11", + "parentId": "[variables('huntingQueryId11')]", + "contentId": "[variables('_huntingQuerycontentId11')]", + "kind": "HuntingQuery", + "version": "[variables('huntingQueryVersion11')]", "source": { "kind": "Solution", "name": "Azure Activity", @@ -2891,100 +2816,59 @@ } } ] - } - } - }, - { - "type": "Microsoft.Resources/templateSpecs", - "apiVersion": "2022-02-01", - "name": "[variables('analyticRuleTemplateSpecName11')]", - "location": "[parameters('workspace-location')]", - "tags": { - "hidden-sentinelWorkspaceId": "[variables('workspaceResourceId')]", - "hidden-sentinelContentType": "AnalyticsRule" - }, - "properties": { - "description": "Azure Activity Analytics Rule 11 with template", - "displayName": "Azure Activity Analytics Rule template" + }, + "packageKind": "Solution", + "packageVersion": "[variables('_solutionVersion')]", + "packageName": "[variables('_solutionName')]", + "packageId": "[variables('_solutionId')]", + "contentSchemaVersion": "3.0.0", + "contentId": "[variables('_huntingQuerycontentId11')]", + "contentKind": "HuntingQuery", + "displayName": "Creation of an anomalous number of resources", + "contentProductId": "[variables('_huntingQuerycontentProductId11')]", + "id": "[variables('_huntingQuerycontentProductId11')]", + "version": "[variables('huntingQueryVersion11')]" } }, { - "type": "Microsoft.Resources/templateSpecs/versions", - "apiVersion": "2022-02-01", - "name": "[concat(variables('analyticRuleTemplateSpecName11'),'/',variables('analyticRuleVersion11'))]", + "type": "Microsoft.OperationalInsights/workspaces/providers/contentTemplates", + "apiVersion": "2023-04-01-preview", + "name": "[variables('huntingQueryTemplateSpecName12')]", "location": "[parameters('workspace-location')]", - "tags": { - "hidden-sentinelWorkspaceId": "[variables('workspaceResourceId')]", - "hidden-sentinelContentType": "AnalyticsRule" - }, "dependsOn": [ - "[resourceId('Microsoft.Resources/templateSpecs', variables('analyticRuleTemplateSpecName11'))]" + "[extensionResourceId(resourceId('Microsoft.OperationalInsights/workspaces', parameters('workspace')), 'Microsoft.SecurityInsights/contentPackages', variables('_solutionId'))]" ], "properties": { - "description": "RareOperations_AnalyticalRules Analytics Rule with template version 2.0.6", + "description": "Granting_Permissions_to_Account_HuntingQueries Hunting Query with template version 3.0.0", "mainTemplate": { "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", - "contentVersion": "[variables('analyticRuleVersion11')]", + "contentVersion": "[variables('huntingQueryVersion12')]", "parameters": {}, "variables": {}, "resources": [ { - "type": "Microsoft.SecurityInsights/AlertRuleTemplates", - "name": "[variables('AnalyticRulecontentId11')]", - "apiVersion": "2022-04-01-preview", - "kind": "Scheduled", + "type": "Microsoft.OperationalInsights/savedSearches", + "apiVersion": "2022-10-01", + "name": "Azure_Activity_Hunting_Query_12", "location": "[parameters('workspace-location')]", "properties": { - "description": "This query looks for a few sensitive subscription-level events based on Azure Activity Logs. For example, this monitors for the operation name 'Create or Update Snapshot', which is used for creating backups but could be misused by attackers to dump hashes or extract sensitive information from the disk.", - "displayName": "Rare subscription-level operations in Azure", - "enabled": false, - "query": "let starttime = 14d;\nlet endtime = 1d;\n// The number of operations above which an IP address is considered an unusual source of role assignment operations\nlet alertOperationThreshold = 5;\n// Add or remove operation names below as per your requirements. For operations lists, please refer to https://learn.microsoft.com/en-us/Azure/role-based-access-control/resource-provider-operations#all\nlet SensitiveOperationList = dynamic([\"microsoft.compute/snapshots/write\", \"microsoft.network/networksecuritygroups/write\", \"microsoft.storage/storageaccounts/listkeys/action\"]);\nlet SensitiveActivity = AzureActivity\n| where OperationNameValue in~ (SensitiveOperationList) or OperationNameValue hassuffix \"listkeys/action\"\n| where ActivityStatusValue =~ \"Success\";\nSensitiveActivity\n| where TimeGenerated between (ago(starttime) .. ago(endtime))\n| summarize count() by CallerIpAddress, Caller, OperationNameValue, bin(TimeGenerated,1d)\n| where count_ >= alertOperationThreshold\n// Returns all the records from the right side that don't have matches from the left\n| join kind = rightanti (\nSensitiveActivity\n| where TimeGenerated >= ago(endtime)\n| summarize StartTimeUtc = min(TimeGenerated), EndTimeUtc = max(TimeGenerated), ActivityTimeStamp = make_list(TimeGenerated), ActivityStatusValue = make_list(ActivityStatusValue), CorrelationIds = make_list(CorrelationId), ResourceGroups = make_list(ResourceGroup), ResourceIds = make_list(_ResourceId), ActivityCountByCallerIPAddress = count()\nby CallerIpAddress, Caller, OperationNameValue\n| where ActivityCountByCallerIPAddress >= alertOperationThreshold\n) on CallerIpAddress, Caller, OperationNameValue\n| extend Name = tostring(split(Caller,'@',0)[0]), UPNSuffix = tostring(split(Caller,'@',1)[0])\n", - "queryFrequency": "P1D", - "queryPeriod": "P14D", - "severity": "Low", - "suppressionDuration": "PT1H", - "suppressionEnabled": false, - "triggerOperator": "GreaterThan", - "triggerThreshold": 0, - "status": "Available", - "requiredDataConnectors": [ + "eTag": "*", + "displayName": "Granting permissions to account", + "category": "Hunting Queries", + "query": "AzureActivity\n| where OperationName =~ \"Create role assignment\"\n| where ActivityStatus =~ \"Succeeded\" \n| project Caller, CallerIpAddress\n| evaluate basket()\n// Returns all the records from the left side and only matching records from the right side.\n| join kind=leftouter (AzureActivity\n| where OperationName =~ \"Create role assignment\"\n| where ActivityStatus =~ \"Succeeded\"\n| summarize StartTime = min(TimeGenerated), EndTime = max(TimeGenerated) by Caller, CallerIpAddress)\non Caller, CallerIpAddress\n| project-away Caller1, CallerIpAddress1\n| where isnotempty(StartTime)\n| extend Name = tostring(split(Caller,'@',0)[0]), UPNSuffix = tostring(split(Caller,'@',1)[0])\n| extend Account_0_Name = Name\n| extend Account_0_UPNSuffix = UPNSuffix\n| extend IP_0_Address = CallerIpAddress\n", + "version": 2, + "tags": [ { - "dataTypes": [ - "AzureActivity" - ], - "connectorId": "AzureActivity" - } - ], - "tactics": [ - "CredentialAccess", - "Persistence" - ], - "techniques": [ - "T1003", - "T1098" - ], - "entityMappings": [ + "name": "description", + "value": "Shows the most prevalent users who grant access to others on Azure resources. List the common source IP address for each of those accounts. If an operation is not from those IP addresses, it may be worthy of investigation." + }, { - "entityType": "Account", - "fieldMappings": [ - { - "columnName": "Name", - "identifier": "Name" - }, - { - "columnName": "UPNSuffix", - "identifier": "UPNSuffix" - } - ] + "name": "tactics", + "value": "Persistence,PrivilegeEscalation" }, { - "entityType": "IP", - "fieldMappings": [ - { - "columnName": "CallerIpAddress", - "identifier": "Address" - } - ] + "name": "techniques", + "value": "T1098" } ] } @@ -2992,13 +2876,13 @@ { "type": "Microsoft.OperationalInsights/workspaces/providers/metadata", "apiVersion": "2022-01-01-preview", - "name": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/',concat('AnalyticsRule-', last(split(variables('analyticRuleId11'),'/'))))]", + "name": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/',concat('HuntingQuery-', last(split(variables('huntingQueryId12'),'/'))))]", "properties": { - "description": "Azure Activity Analytics Rule 11", - "parentId": "[variables('analyticRuleId11')]", - "contentId": "[variables('_analyticRulecontentId11')]", - "kind": "AnalyticsRule", - "version": "[variables('analyticRuleVersion11')]", + "description": "Azure Activity Hunting Query 12", + "parentId": "[variables('huntingQueryId12')]", + "contentId": "[variables('_huntingQuerycontentId12')]", + "kind": "HuntingQuery", + "version": "[variables('huntingQueryVersion12')]", "source": { "kind": "Solution", "name": "Azure Activity", @@ -3017,93 +2901,59 @@ } } ] - } - } - }, - { - "type": "Microsoft.Resources/templateSpecs", - "apiVersion": "2022-02-01", - "name": "[variables('analyticRuleTemplateSpecName12')]", - "location": "[parameters('workspace-location')]", - "tags": { - "hidden-sentinelWorkspaceId": "[variables('workspaceResourceId')]", - "hidden-sentinelContentType": "AnalyticsRule" - }, - "properties": { - "description": "Azure Activity Analytics Rule 12 with template", - "displayName": "Azure Activity Analytics Rule template" + }, + "packageKind": "Solution", + "packageVersion": "[variables('_solutionVersion')]", + "packageName": "[variables('_solutionName')]", + "packageId": "[variables('_solutionId')]", + "contentSchemaVersion": "3.0.0", + "contentId": "[variables('_huntingQuerycontentId12')]", + "contentKind": "HuntingQuery", + "displayName": "Granting permissions to account", + "contentProductId": "[variables('_huntingQuerycontentProductId12')]", + "id": "[variables('_huntingQuerycontentProductId12')]", + "version": "[variables('huntingQueryVersion12')]" } }, { - "type": "Microsoft.Resources/templateSpecs/versions", - "apiVersion": "2022-02-01", - "name": "[concat(variables('analyticRuleTemplateSpecName12'),'/',variables('analyticRuleVersion12'))]", + "type": "Microsoft.OperationalInsights/workspaces/providers/contentTemplates", + "apiVersion": "2023-04-01-preview", + "name": "[variables('huntingQueryTemplateSpecName13')]", "location": "[parameters('workspace-location')]", - "tags": { - "hidden-sentinelWorkspaceId": "[variables('workspaceResourceId')]", - "hidden-sentinelContentType": "AnalyticsRule" - }, "dependsOn": [ - "[resourceId('Microsoft.Resources/templateSpecs', variables('analyticRuleTemplateSpecName12'))]" + "[extensionResourceId(resourceId('Microsoft.OperationalInsights/workspaces', parameters('workspace')), 'Microsoft.SecurityInsights/contentPackages', variables('_solutionId'))]" ], "properties": { - "description": "TimeSeriesAnomaly_Mass_Cloud_Resource_Deletions_AnalyticalRules Analytics Rule with template version 2.0.6", + "description": "PortOpenedForAzureResource_HuntingQueries Hunting Query with template version 3.0.0", "mainTemplate": { "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", - "contentVersion": "[variables('analyticRuleVersion12')]", - "parameters": {}, - "variables": {}, - "resources": [ - { - "type": "Microsoft.SecurityInsights/AlertRuleTemplates", - "name": "[variables('AnalyticRulecontentId12')]", - "apiVersion": "2022-04-01-preview", - "kind": "Scheduled", - "location": "[parameters('workspace-location')]", - "properties": { - "description": "This query generates the baseline pattern of cloud resource deletions by an individual and generates an anomaly when any unusual spike is detected. These anomalies from unusual or privileged users could be an indication of a cloud infrastructure takedown by an adversary.", - "displayName": "Mass Cloud resource deletions Time Series Anomaly", - "enabled": false, - "query": "let starttime = 14d;\nlet endtime = 1d;\nlet timeframe = 1d;\nlet TotalEventsThreshold = 25;\nlet TimeSeriesData = AzureActivity \n| where TimeGenerated between (startofday(ago(starttime))..startofday(now())) \n| where OperationNameValue endswith \"delete\" \n| project TimeGenerated, Caller \n| make-series Total = count() on TimeGenerated from startofday(ago(starttime)) to startofday(now()) step timeframe by Caller;\nTimeSeriesData \n| extend (anomalies, score, baseline) = series_decompose_anomalies(Total, 3, -1, 'linefit') \n| mv-expand Total to typeof(double), TimeGenerated to typeof(datetime), anomalies to typeof(double), score to typeof(double), baseline to typeof(long) \n| where TimeGenerated >= startofday(ago(endtime)) \n| where anomalies > 0 \n| project Caller, TimeGenerated, Total, baseline, anomalies, score \n| where Total > TotalEventsThreshold and baseline > 0 \n| join (AzureActivity \n| where TimeGenerated > startofday(ago(endtime)) \n| where OperationNameValue endswith \"delete\" \n| summarize count(), make_set(OperationNameValue,100), make_set(_ResourceId,100) by bin(TimeGenerated, timeframe), Caller ) on TimeGenerated, Caller \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 '@',Caller,\"\")\n", - "queryFrequency": "P1D", - "queryPeriod": "P14D", - "severity": "Medium", - "suppressionDuration": "PT1H", - "suppressionEnabled": false, - "triggerOperator": "GreaterThan", - "triggerThreshold": 0, - "status": "Available", - "requiredDataConnectors": [ + "contentVersion": "[variables('huntingQueryVersion13')]", + "parameters": {}, + "variables": {}, + "resources": [ + { + "type": "Microsoft.OperationalInsights/savedSearches", + "apiVersion": "2022-10-01", + "name": "Azure_Activity_Hunting_Query_13", + "location": "[parameters('workspace-location')]", + "properties": { + "eTag": "*", + "displayName": "Port opened for an Azure Resource", + "category": "Hunting Queries", + "query": "let lookback = 7d;\nAzureActivity\n| where TimeGenerated >= ago(lookback)\n| where OperationNameValue has_any (\"ipfilterrules\", \"securityRules\", \"publicIPAddresses\", \"firewallrules\") and OperationNameValue endswith \"write\"\n// Choosing Accepted here because it has the Rule Attributes included\n| where ActivityStatusValue == \"Accepted\" \n// If there is publicIP info, include it\n| extend parsed_properties = parse_json(tostring(parse_json(Properties).responseBody)).properties\n| extend publicIPAddressVersion = case(Properties has_cs 'publicIPAddressVersion',tostring(parsed_properties.publicIPAddressVersion),\"\")\n| extend publicIPAllocationMethod = case(Properties has_cs 'publicIPAllocationMethod',tostring(parsed_properties.publicIPAllocationMethod),\"\")\n// Include rule attributes for context\n| extend access = case(Properties has_cs 'access',tostring(parsed_properties.access),\"\")\n| extend description = case(Properties has_cs 'description',tostring(parsed_properties.description),\"\")\n| extend destinationPortRange = case(Properties has_cs 'destinationPortRange',tostring(parsed_properties.destinationPortRange),\"\")\n| extend direction = case(Properties has_cs 'direction',tostring(parsed_properties.direction),\"\")\n| extend protocol = case(Properties has_cs 'protocol',tostring(parsed_properties.protocol),\"\")\n| extend sourcePortRange = case(Properties has_cs 'sourcePortRange',tostring(parsed_properties.sourcePortRange),\"\")\n| summarize StartTime = min(TimeGenerated), EndTime = max(TimeGenerated), ResourceIds = make_set(_ResourceId,100) by Caller, CallerIpAddress, Resource, ResourceGroup, \nActivityStatusValue, ActivitySubstatus, SubscriptionId, access, description, destinationPortRange, direction, protocol, sourcePortRange, publicIPAddressVersion, publicIPAllocationMethod\n| extend Name = tostring(split(Caller,'@',0)[0]), UPNSuffix = tostring(split(Caller,'@',1)[0])\n| extend Account_0_Name = Name\n| extend Account_0_UPNSuffix = UPNSuffix\n| extend IP_0_Address = CallerIpAddress\n", + "version": 2, + "tags": [ { - "dataTypes": [ - "AzureActivity" - ], - "connectorId": "AzureActivity" - } - ], - "tactics": [ - "Impact" - ], - "techniques": [ - "T1485" - ], - "entityMappings": [ + "name": "description", + "value": "Identifies what ports may have been opened for a given Azure Resource over the last 7 days." + }, { - "entityType": "Account", - "fieldMappings": [ - { - "columnName": "Name", - "identifier": "Name" - }, - { - "columnName": "UPNSuffix", - "identifier": "UPNSuffix" - }, - { - "columnName": "AadUserId", - "identifier": "AadUserId" - } - ] + "name": "tactics", + "value": "CommandAndControl,Impact" + }, + { + "name": "techniques", + "value": "T1071,T1571,T1496" } ] } @@ -3111,13 +2961,13 @@ { "type": "Microsoft.OperationalInsights/workspaces/providers/metadata", "apiVersion": "2022-01-01-preview", - "name": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/',concat('AnalyticsRule-', last(split(variables('analyticRuleId12'),'/'))))]", + "name": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/',concat('HuntingQuery-', last(split(variables('huntingQueryId13'),'/'))))]", "properties": { - "description": "Azure Activity Analytics Rule 12", - "parentId": "[variables('analyticRuleId12')]", - "contentId": "[variables('_analyticRulecontentId12')]", - "kind": "AnalyticsRule", - "version": "[variables('analyticRuleVersion12')]", + "description": "Azure Activity Hunting Query 13", + "parentId": "[variables('huntingQueryId13')]", + "contentId": "[variables('_huntingQuerycontentId13')]", + "kind": "HuntingQuery", + "version": "[variables('huntingQueryVersion13')]", "source": { "kind": "Solution", "name": "Azure Activity", @@ -3136,70 +2986,73 @@ } } ] - } - } - }, - { - "type": "Microsoft.Resources/templateSpecs", - "apiVersion": "2022-02-01", - "name": "[variables('workbookTemplateSpecName1')]", - "location": "[parameters('workspace-location')]", - "tags": { - "hidden-sentinelWorkspaceId": "[variables('workspaceResourceId')]", - "hidden-sentinelContentType": "Workbook" - }, - "properties": { - "description": "Azure Activity Workbook with template", - "displayName": "Azure Activity workbook template" + }, + "packageKind": "Solution", + "packageVersion": "[variables('_solutionVersion')]", + "packageName": "[variables('_solutionName')]", + "packageId": "[variables('_solutionId')]", + "contentSchemaVersion": "3.0.0", + "contentId": "[variables('_huntingQuerycontentId13')]", + "contentKind": "HuntingQuery", + "displayName": "Port opened for an Azure Resource", + "contentProductId": "[variables('_huntingQuerycontentProductId13')]", + "id": "[variables('_huntingQuerycontentProductId13')]", + "version": "[variables('huntingQueryVersion13')]" } }, { - "type": "Microsoft.Resources/templateSpecs/versions", - "apiVersion": "2022-02-01", - "name": "[concat(variables('workbookTemplateSpecName1'),'/',variables('workbookVersion1'))]", + "type": "Microsoft.OperationalInsights/workspaces/providers/contentTemplates", + "apiVersion": "2023-04-01-preview", + "name": "[variables('huntingQueryTemplateSpecName14')]", "location": "[parameters('workspace-location')]", - "tags": { - "hidden-sentinelWorkspaceId": "[variables('workspaceResourceId')]", - "hidden-sentinelContentType": "Workbook" - }, "dependsOn": [ - "[resourceId('Microsoft.Resources/templateSpecs', variables('workbookTemplateSpecName1'))]" + "[extensionResourceId(resourceId('Microsoft.OperationalInsights/workspaces', parameters('workspace')), 'Microsoft.SecurityInsights/contentPackages', variables('_solutionId'))]" ], "properties": { - "description": "AzureActivityWorkbook with template version 2.0.6", + "description": "Rare_Custom_Script_Extension_HuntingQueries Hunting Query with template version 3.0.0", "mainTemplate": { "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", - "contentVersion": "[variables('workbookVersion1')]", + "contentVersion": "[variables('huntingQueryVersion14')]", "parameters": {}, "variables": {}, "resources": [ { - "type": "Microsoft.Insights/workbooks", - "name": "[variables('workbookContentId1')]", + "type": "Microsoft.OperationalInsights/savedSearches", + "apiVersion": "2022-10-01", + "name": "Azure_Activity_Hunting_Query_14", "location": "[parameters('workspace-location')]", - "kind": "shared", - "apiVersion": "2021-08-01", - "metadata": { - "description": "Gain extensive insight into your organization's Azure Activity by analyzing, and correlating all user operations and events.\nYou can learn about all user operations, trends, and anomalous changes over time.\nThis workbook gives you the ability to drill down into caller activities and summarize detected failure and warning events." - }, "properties": { - "displayName": "[parameters('workbook1-name')]", - "serializedData": "{\"version\":\"Notebook/1.0\",\"items\":[{\"type\":9,\"content\":{\"version\":\"KqlParameterItem/1.0\",\"query\":\"\",\"crossComponentResources\":\"[variables('TemplateEmptyArray')]\",\"parameters\":[{\"id\":\"52bfbd84-1639-480c-bda5-bfc87fd81832\",\"version\":\"KqlParameterItem/1.0\",\"name\":\"TimeRange\",\"type\":4,\"isRequired\":true,\"value\":{\"durationMs\":604800000},\"typeSettings\":{\"selectableValues\":[{\"durationMs\":300000},{\"durationMs\":900000},{\"durationMs\":1800000},{\"durationMs\":3600000},{\"durationMs\":14400000},{\"durationMs\":43200000},{\"durationMs\":86400000},{\"durationMs\":172800000},{\"durationMs\":259200000},{\"durationMs\":604800000},{\"durationMs\":1209600000},{\"durationMs\":2419200000},{\"durationMs\":2592000000},{\"durationMs\":5184000000},{\"durationMs\":7776000000}]}},{\"id\":\"eeb5dcf9-e898-46af-9c12-d91d97e13cd3\",\"version\":\"KqlParameterItem/1.0\",\"name\":\"Caller\",\"type\":2,\"isRequired\":true,\"multiSelect\":true,\"quote\":\"'\",\"delimiter\":\",\",\"query\":\"AzureActivity\\r\\n| summarize by Caller\",\"value\":[\"value::all\"],\"typeSettings\":{\"additionalResourceOptions\":[\"value::all\"],\"selectAllValue\":\"All\"},\"timeContext\":{\"durationMs\":0},\"timeContextFromParameter\":\"TimeRange\",\"queryType\":0,\"resourceType\":\"microsoft.operationalinsights/workspaces\"},{\"id\":\"46375a76-7ae1-4d7e-9082-4191531198a9\",\"version\":\"KqlParameterItem/1.0\",\"name\":\"ResourceGroup\",\"type\":2,\"isRequired\":true,\"multiSelect\":true,\"quote\":\"'\",\"delimiter\":\",\",\"query\":\"AzureActivity\\r\\n| summarize by ResourceGroup\",\"value\":[\"value::all\"],\"typeSettings\":{\"resourceTypeFilter\":{\"microsoft.resources/resourcegroups\":true},\"additionalResourceOptions\":[\"value::all\"],\"selectAllValue\":\"All\"},\"timeContext\":{\"durationMs\":0},\"timeContextFromParameter\":\"TimeRange\",\"queryType\":0,\"resourceType\":\"microsoft.operationalinsights/workspaces\"}],\"style\":\"pills\",\"queryType\":0,\"resourceType\":\"microsoft.operationalinsights/workspaces\"},\"name\":\"parameters - 2\"},{\"type\":3,\"content\":{\"version\":\"KqlItem/1.0\",\"query\":\"let data = AzureActivity\\r\\n| where \\\"{Caller:lable}\\\" == \\\"All\\\" or \\\"{Caller:lable}\\\" == \\\"All\\\" or Caller in ({Caller})\\r\\n| where \\\"{ResourceGroup:lable}\\\" == \\\"All\\\" or \\\"{ResourceGroup:lable}\\\" == \\\"All\\\" or ResourceGroup in ({ResourceGroup});\\r\\ndata\\r\\n| summarize Count = count() by ResourceGroup\\r\\n| join kind = fullouter (datatable(ResourceGroup:string)['Medium', 'high', 'low']) on ResourceGroup\\r\\n| project ResourceGroup = iff(ResourceGroup == '', ResourceGroup1, ResourceGroup), Count = iff(ResourceGroup == '', 0, Count)\\r\\n| join kind = inner (data\\r\\n | make-series Trend = count() default = 0 on TimeGenerated from {TimeRange:start} to {TimeRange:end} step {TimeRange:grain} by ResourceGroup)\\r\\n on ResourceGroup\\r\\n| project-away ResourceGroup1, TimeGenerated\\r\\n| extend ResourceGroups = ResourceGroup\\r\\n| union (\\r\\n data \\r\\n | summarize Count = count() \\r\\n | extend jkey = 1\\r\\n | join kind=inner (data\\r\\n | make-series Trend = count() default = 0 on TimeGenerated from {TimeRange:start} to {TimeRange:end} step {TimeRange:grain}\\r\\n | extend jkey = 1) on jkey\\r\\n | extend ResourceGroup = 'All', ResourceGroups = '*' \\r\\n)\\r\\n| order by Count desc\\r\\n| take 10\",\"size\":4,\"exportToExcelOptions\":\"visible\",\"title\":\"Top 10 active resource groups\",\"timeContext\":{\"durationMs\":0},\"timeContextFromParameter\":\"TimeRange\",\"queryType\":0,\"resourceType\":\"microsoft.operationalinsights/workspaces\",\"visualization\":\"tiles\",\"tileSettings\":{\"titleContent\":{\"columnMatch\":\"ResourceGroup\",\"formatter\":1,\"formatOptions\":{\"showIcon\":true}},\"leftContent\":{\"columnMatch\":\"Count\",\"formatter\":12,\"formatOptions\":{\"palette\":\"auto\",\"showIcon\":true},\"numberFormat\":{\"unit\":17,\"options\":{\"maximumSignificantDigits\":3,\"maximumFractionDigits\":2}}},\"secondaryContent\":{\"columnMatch\":\"Trend\",\"formatter\":9,\"formatOptions\":{\"palette\":\"blueOrange\",\"showIcon\":true}},\"showBorder\":false}},\"name\":\"query - 3\"},{\"type\":3,\"content\":{\"version\":\"KqlItem/1.0\",\"query\":\"AzureActivity\\r\\n| where \\\"{Caller:lable}\\\" == \\\"All\\\" or Caller in ({Caller})\\r\\n| where \\\"{ResourceGroup:lable}\\\" == \\\"All\\\" or ResourceGroup in ({ResourceGroup})\\r\\n| summarize deletions = countif(OperationNameValue hassuffix \\\"delete\\\"), creations = countif(OperationNameValue hassuffix \\\"write\\\"), updates = countif(OperationNameValue hassuffix \\\"write\\\"), Activities = count(OperationNameValue) by bin_at(TimeGenerated, 1h, now())\\r\\n\",\"size\":0,\"exportToExcelOptions\":\"visible\",\"title\":\"Activities over time\",\"color\":\"gray\",\"timeContext\":{\"durationMs\":0},\"timeContextFromParameter\":\"TimeRange\",\"queryType\":0,\"resourceType\":\"microsoft.operationalinsights/workspaces\",\"visualization\":\"linechart\",\"graphSettings\":{\"type\":0}},\"name\":\"query - 1\"},{\"type\":3,\"content\":{\"version\":\"KqlItem/1.0\",\"query\":\"AzureActivity\\r\\n| where \\\"{Caller:lable}\\\" == \\\"All\\\" or Caller in ({Caller})\\r\\n| where \\\"{ResourceGroup:lable}\\\" == \\\"All\\\" or ResourceGroup in ({ResourceGroup})\\r\\n| summarize deletions = countif(OperationNameValue hassuffix \\\"Delete\\\"), creations = countif(OperationNameValue hassuffix \\\"write\\\"), updates = countif(OperationNameValue hassuffix \\\"write\\\"), Activities = count() by Caller\\r\\n\",\"size\":1,\"exportToExcelOptions\":\"visible\",\"title\":\"Caller activities\",\"timeContext\":{\"durationMs\":0},\"timeContextFromParameter\":\"TimeRange\",\"queryType\":0,\"resourceType\":\"microsoft.operationalinsights/workspaces\",\"gridSettings\":{\"formatters\":[{\"columnMatch\":\"Caller\",\"formatter\":0,\"formatOptions\":{\"showIcon\":true}},{\"columnMatch\":\"deletions\",\"formatter\":4,\"formatOptions\":{\"showIcon\":true,\"aggregation\":\"Count\"}},{\"columnMatch\":\"creations\",\"formatter\":4,\"formatOptions\":{\"palette\":\"purple\",\"showIcon\":true,\"aggregation\":\"Count\"}},{\"columnMatch\":\"updates\",\"formatter\":4,\"formatOptions\":{\"palette\":\"gray\",\"showIcon\":true,\"aggregation\":\"Count\"}},{\"columnMatch\":\"Activities\",\"formatter\":4,\"formatOptions\":{\"palette\":\"greenDark\",\"linkTarget\":\"GenericDetails\",\"linkIsContextBlade\":true,\"showIcon\":true,\"aggregation\":\"Count\",\"workbookContext\":{\"componentIdSource\":\"workbook\",\"resourceIdsSource\":\"workbook\",\"templateIdSource\":\"static\",\"templateId\":\"https://go.microsoft.com/fwlink/?linkid=874159&resourceId=%2Fsubscriptions%2F44e4eff8-1fcb-4a22-a7d6-992ac7286382%2FresourceGroups%2FSOC&featureName=Workbooks&itemId=%2Fsubscriptions%2F44e4eff8-1fcb-4a22-a7d6-992ac7286382%2Fresourcegroups%2Fsoc%2Fproviders%2Fmicrosoft.insights%2Fworkbooks%2F4c195aec-747f-40bb-addb-934acb3ec646&name=CiscoASA&func=NavigateToPortalFeature&type=workbook\",\"typeSource\":\"workbook\",\"gallerySource\":\"workbook\"}}}],\"sortBy\":[{\"itemKey\":\"$gen_bar_updates_3\",\"sortOrder\":2}],\"labelSettings\":\"[variables('TemplateEmptyArray')]\"}},\"name\":\"query - 1\"},{\"type\":3,\"content\":{\"version\":\"KqlItem/1.0\",\"query\":\"AzureActivity \\r\\n| where \\\"{Caller:lable}\\\" == \\\"All\\\" or Caller in ({Caller})\\r\\n| where \\\"{ResourceGroup:lable}\\\" == \\\"All\\\" or ResourceGroup in ({ResourceGroup})\\r\\n| summarize Informational = countif(Level == \\\"Informational\\\"), Warning = countif(Level == \\\"Warning\\\"), Error = countif(Level == \\\"Error\\\") by bin_at(TimeGenerated, 1h, now())\\r\\n\",\"size\":0,\"exportToExcelOptions\":\"visible\",\"title\":\"Activities by log level over time\",\"color\":\"redBright\",\"timeContext\":{\"durationMs\":0},\"timeContextFromParameter\":\"TimeRange\",\"queryType\":0,\"resourceType\":\"microsoft.operationalinsights/workspaces\",\"visualization\":\"scatterchart\",\"tileSettings\":{\"showBorder\":false},\"graphSettings\":{\"type\":2,\"topContent\":{\"columnMatch\":\"Error\",\"formatter\":12,\"formatOptions\":{\"showIcon\":true}},\"hivesContent\":{\"columnMatch\":\"TimeGenerated\",\"formatter\":1,\"formatOptions\":{\"showIcon\":true}},\"nodeIdField\":\"Error\",\"sourceIdField\":\"Error\",\"targetIdField\":\"Error\",\"nodeSize\":\"[variables('blanks')]\",\"staticNodeSize\":100,\"colorSettings\":\"[variables('blanks')]\",\"groupByField\":\"TimeGenerated\",\"hivesMargin\":5}},\"name\":\"query - 4\"}],\"fromTemplateId\":\"sentinel-AzureActivity\",\"$schema\":\"https://github.com/Microsoft/Application-Insights-Workbooks/blob/master/schema/workbook.json\"}\r\n", - "version": "1.0", - "sourceId": "[variables('workspaceResourceId')]", - "category": "sentinel" + "eTag": "*", + "displayName": "Rare Custom Script Extension", + "category": "Hunting Queries", + "query": "let starttime = todatetime('{{StartTimeISO}}');\nlet endtime = todatetime('{{EndTimeISO}}');\nlet Lookback = starttime - 14d;\nlet CustomScriptExecution = AzureActivity\n| where TimeGenerated >= Lookback\n| where OperationName =~ \"Create or Update Virtual Machine Extension\"\n| extend parsed_properties = parse_json(Properties)\n| extend Settings = tostring((parse_json(tostring(parsed_properties.responseBody)).properties).settings)\n| parse Settings with * 'fileUris\":[' FileURI \"]\" *\n| parse Settings with * 'commandToExecute\":' commandToExecute '}' *\n| extend message_ = tostring((parse_json(tostring(parsed_properties.statusMessage)).error).message);\nlet LookbackCustomScriptExecution = CustomScriptExecution\n| where TimeGenerated >= Lookback and TimeGenerated < starttime\n| where isnotempty(FileURI) and isnotempty(commandToExecute)\n| summarize max(TimeGenerated), OperationCount = count() by Caller, Resource, CallerIpAddress, FileURI, commandToExecute;\nlet CurrentCustomScriptExecution = CustomScriptExecution\n| where TimeGenerated between (starttime..endtime)\n| where isnotempty(FileURI) and isnotempty(commandToExecute)\n| project TimeGenerated, ActivityStatus, OperationId, CorrelationId, ResourceId, CallerIpAddress, Caller, OperationName, Resource, ResourceGroup, FileURI, commandToExecute, FailureMessage = message_, HTTPRequest, Settings;\nlet RareCustomScriptExecution = CurrentCustomScriptExecution\n| join kind= leftanti (LookbackCustomScriptExecution) on Caller, CallerIpAddress, FileURI, commandToExecute;\nlet IPCheck = RareCustomScriptExecution\n| summarize arg_max(TimeGenerated, OperationName), OperationIds = make_set(OperationId,100), CallerIpAddresses = make_set(CallerIpAddress,100) by ActivityStatus, CorrelationId, ResourceId, Caller, Resource, ResourceGroup, FileURI, commandToExecute, FailureMessage\n| extend IPArray = array_length(CallerIpAddresses);\n//Get IPs for later summarization so all associated CorrelationIds and Caller actions have an IP. Success and Fails do not always have IP\nlet multiIP = IPCheck | where IPArray > 1\n| mv-expand CallerIpAddresses | extend CallerIpAddress = tostring(CallerIpAddresses)\n| where isnotempty(CallerIpAddresses);\nlet singleIP = IPCheck | where IPArray <= 1\n| mv-expand CallerIpAddresses | extend CallerIpAddress = tostring(CallerIpAddresses);\nlet FullDetails = singleIP | union multiIP;\n//Get IP address associated with successes and fails with no IP listed\nlet IPList = FullDetails | where isnotempty(CallerIpAddress) | summarize by CorrelationId, Caller, CallerIpAddress;\nlet EmptyIP = FullDetails | where isempty(CallerIpAddress) | project-away CallerIpAddress;\nlet IpJoin = EmptyIP | join kind= leftouter (IPList) on CorrelationId, Caller | project-away CorrelationId1, Caller1;\nlet nonEmptyIP = FullDetails | where isnotempty(CallerIpAddress);\nnonEmptyIP | union IpJoin\n// summarize all activities with a given CorrelationId and Caller together so we can provide a singular result\n| summarize StartTime = min(TimeGenerated), EndTime = max(TimeGenerated), ActivityStatusSet = make_set(ActivityStatus,100), OperationIds = make_set(OperationIds,100), FailureMessages = make_set(FailureMessage,100) by CorrelationId, ResourceId, CallerIpAddress, Caller, Resource, ResourceGroup, FileURI, commandToExecute\n| extend Name = tostring(split(Caller,'@',0)[0]), UPNSuffix = tostring(split(Caller,'@',1)[0])\n| extend Account_0_Name = Name\n| extend Account_0_UPNSuffix = UPNSuffix\n| extend IP_0_Address = CallerIpAddress\n", + "version": 2, + "tags": [ + { + "name": "description", + "value": "The Custom Script Extension in Azure executes scripts on VMs, useful for post-deployment tasks. Scripts can be from various sources and could be used maliciously. The query identifies rare custom script extensions executed in your environment." + }, + { + "name": "tactics", + "value": "Execution" + }, + { + "name": "techniques", + "value": "T1059" + } + ] } }, { "type": "Microsoft.OperationalInsights/workspaces/providers/metadata", "apiVersion": "2022-01-01-preview", - "name": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/',concat('Workbook-', last(split(variables('workbookId1'),'/'))))]", + "name": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/',concat('HuntingQuery-', last(split(variables('huntingQueryId14'),'/'))))]", "properties": { - "description": "@{workbookKey=AzureActivityWorkbook; logoFileName=azureactivity_logo.svg; description=Gain extensive insight into your organization's Azure Activity by analyzing, and correlating all user operations and events.\nYou can learn about all user operations, trends, and anomalous changes over time.\nThis workbook gives you the ability to drill down into caller activities and summarize detected failure and warning events.; dataTypesDependencies=System.Object[]; dataConnectorsDependencies=System.Object[]; previewImagesFileNames=System.Object[]; version=2.0.0; title=Azure Activity; templateRelativePath=AzureActivity.json; subtitle=; provider=Microsoft}.description", - "parentId": "[variables('workbookId1')]", - "contentId": "[variables('_workbookContentId1')]", - "kind": "Workbook", - "version": "[variables('workbookVersion1')]", + "description": "Azure Activity Hunting Query 14", + "parentId": "[variables('huntingQueryId14')]", + "contentId": "[variables('_huntingQuerycontentId14')]", + "kind": "HuntingQuery", + "version": "[variables('huntingQueryVersion14')]", "source": { "kind": "Solution", "name": "Azure Activity", @@ -3214,34 +3067,39 @@ "name": "Microsoft Corporation", "email": "support@microsoft.com", "link": "https://support.microsoft.com/" - }, - "dependencies": { - "operator": "AND", - "criteria": [ - { - "contentId": "AzureActivity", - "kind": "DataType" - }, - { - "contentId": "AzureActivity", - "kind": "DataConnector" - } - ] } } } ] - } + }, + "packageKind": "Solution", + "packageVersion": "[variables('_solutionVersion')]", + "packageName": "[variables('_solutionName')]", + "packageId": "[variables('_solutionId')]", + "contentSchemaVersion": "3.0.0", + "contentId": "[variables('_huntingQuerycontentId14')]", + "contentKind": "HuntingQuery", + "displayName": "Rare Custom Script Extension", + "contentProductId": "[variables('_huntingQuerycontentProductId14')]", + "id": "[variables('_huntingQuerycontentProductId14')]", + "version": "[variables('huntingQueryVersion14')]" } }, { - "type": "Microsoft.OperationalInsights/workspaces/providers/metadata", - "apiVersion": "2022-01-01-preview", + "type": "Microsoft.OperationalInsights/workspaces/providers/contentPackages", + "apiVersion": "2023-04-01-preview", "location": "[parameters('workspace-location')]", "properties": { - "version": "2.0.6", + "version": "3.0.0", "kind": "Solution", - "contentSchemaVersion": "2.0.0", + "contentSchemaVersion": "3.0.0", + "displayName": "Azure Activity", + "publisherDisplayName": "Microsoft Sentinel, Microsoft Corporation", + "descriptionHtml": "

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

\n

The Azure Activity solution for Microsoft Sentinel enables you to ingest Azure Activity Administrative, Security, Service Health, Alert, Recommendation, Policy, Autoscale and Resource Health logs using Diagnostic Settings into Microsoft Sentinel.

\n

Data Connectors: 1, Workbooks: 1, Analytic Rules: 12, Hunting Queries: 14

\n

Learn more about Microsoft Sentinel | Learn more about Solutions

\n", + "contentKind": "Solution", + "contentProductId": "[variables('_solutioncontentProductId')]", + "id": "[variables('_solutioncontentProductId')]", + "icon": "", "contentId": "[variables('_solutionId')]", "parentId": "[variables('_solutionId')]", "source": { @@ -3267,6 +3125,71 @@ "contentId": "[variables('_dataConnectorContentId1')]", "version": "[variables('dataConnectorVersion1')]" }, + { + "kind": "Workbook", + "contentId": "[variables('_workbookContentId1')]", + "version": "[variables('workbookVersion1')]" + }, + { + "kind": "AnalyticsRule", + "contentId": "[variables('analyticRulecontentId1')]", + "version": "[variables('analyticRuleVersion1')]" + }, + { + "kind": "AnalyticsRule", + "contentId": "[variables('analyticRulecontentId2')]", + "version": "[variables('analyticRuleVersion2')]" + }, + { + "kind": "AnalyticsRule", + "contentId": "[variables('analyticRulecontentId3')]", + "version": "[variables('analyticRuleVersion3')]" + }, + { + "kind": "AnalyticsRule", + "contentId": "[variables('analyticRulecontentId4')]", + "version": "[variables('analyticRuleVersion4')]" + }, + { + "kind": "AnalyticsRule", + "contentId": "[variables('analyticRulecontentId5')]", + "version": "[variables('analyticRuleVersion5')]" + }, + { + "kind": "AnalyticsRule", + "contentId": "[variables('analyticRulecontentId6')]", + "version": "[variables('analyticRuleVersion6')]" + }, + { + "kind": "AnalyticsRule", + "contentId": "[variables('analyticRulecontentId7')]", + "version": "[variables('analyticRuleVersion7')]" + }, + { + "kind": "AnalyticsRule", + "contentId": "[variables('analyticRulecontentId8')]", + "version": "[variables('analyticRuleVersion8')]" + }, + { + "kind": "AnalyticsRule", + "contentId": "[variables('analyticRulecontentId9')]", + "version": "[variables('analyticRuleVersion9')]" + }, + { + "kind": "AnalyticsRule", + "contentId": "[variables('analyticRulecontentId10')]", + "version": "[variables('analyticRuleVersion10')]" + }, + { + "kind": "AnalyticsRule", + "contentId": "[variables('analyticRulecontentId11')]", + "version": "[variables('analyticRuleVersion11')]" + }, + { + "kind": "AnalyticsRule", + "contentId": "[variables('analyticRulecontentId12')]", + "version": "[variables('analyticRuleVersion12')]" + }, { "kind": "HuntingQuery", "contentId": "[variables('_huntingQuerycontentId1')]", @@ -3336,71 +3259,6 @@ "kind": "HuntingQuery", "contentId": "[variables('_huntingQuerycontentId14')]", "version": "[variables('huntingQueryVersion14')]" - }, - { - "kind": "AnalyticsRule", - "contentId": "[variables('analyticRulecontentId1')]", - "version": "[variables('analyticRuleVersion1')]" - }, - { - "kind": "AnalyticsRule", - "contentId": "[variables('analyticRulecontentId2')]", - "version": "[variables('analyticRuleVersion2')]" - }, - { - "kind": "AnalyticsRule", - "contentId": "[variables('analyticRulecontentId3')]", - "version": "[variables('analyticRuleVersion3')]" - }, - { - "kind": "AnalyticsRule", - "contentId": "[variables('analyticRulecontentId4')]", - "version": "[variables('analyticRuleVersion4')]" - }, - { - "kind": "AnalyticsRule", - "contentId": "[variables('analyticRulecontentId5')]", - "version": "[variables('analyticRuleVersion5')]" - }, - { - "kind": "AnalyticsRule", - "contentId": "[variables('analyticRulecontentId6')]", - "version": "[variables('analyticRuleVersion6')]" - }, - { - "kind": "AnalyticsRule", - "contentId": "[variables('analyticRulecontentId7')]", - "version": "[variables('analyticRuleVersion7')]" - }, - { - "kind": "AnalyticsRule", - "contentId": "[variables('analyticRulecontentId8')]", - "version": "[variables('analyticRuleVersion8')]" - }, - { - "kind": "AnalyticsRule", - "contentId": "[variables('analyticRulecontentId9')]", - "version": "[variables('analyticRuleVersion9')]" - }, - { - "kind": "AnalyticsRule", - "contentId": "[variables('analyticRulecontentId10')]", - "version": "[variables('analyticRuleVersion10')]" - }, - { - "kind": "AnalyticsRule", - "contentId": "[variables('analyticRulecontentId11')]", - "version": "[variables('analyticRuleVersion11')]" - }, - { - "kind": "AnalyticsRule", - "contentId": "[variables('analyticRulecontentId12')]", - "version": "[variables('analyticRuleVersion12')]" - }, - { - "kind": "Workbook", - "contentId": "[variables('_workbookContentId1')]", - "version": "[variables('workbookVersion1')]" } ] }, diff --git a/Solutions/Azure Activity/ReleaseNotes.md b/Solutions/Azure Activity/ReleaseNotes.md new file mode 100644 index 00000000000..d906ae1c8bb --- /dev/null +++ b/Solutions/Azure Activity/ReleaseNotes.md @@ -0,0 +1,4 @@ +| **Version** | **Date Modified (DD-MM-YYYY)** | **Change History** | +|-------------|--------------------------------|--------------------------------------------------------------------| +| 3.0.0 | 30-10-2023 | Optimized the **Analytic Rule** query logic to achieve expected results | +