Query Details

Security Nested Recommendation Virtual Machines MDVM Vulnerability Assessments

Query

let query_period = 120d;
SecurityNestedRecommendation
| where TimeGenerated > ago(query_period) and ParentRecommendationId in ("1195afff-c881-495e-9bc5-1486211ae03f", "77a4a140-e051-481a-84cc-d4bf2109bd65") // 4ab6e3c5-74dd-8b35-9ab9-f61b30875b27 // e1145ab1-eb4f-43d8-911b-36ddf771d13f
// 1195afff-c881-495e-9bc5-1486211ae03f "Agentless Microsoft Defender vulnerability management"|"Microsoft Defender vulnerability management" Source =="Azure" CloudResourceLocation in ("", "AwsMultiCloud", ...)
// 77a4a140-e051-481a-84cc-d4bf2109bd65 "Agentless Microsoft Defender vulnerability management" Source =="Aws"
| summarize hint.strategy=shuffle
    StartSubAssessmentTimeGeneration = min(SubAssessmentTimeGeneration),
    EndSubAssessmentTimeGeneration = arg_max(SubAssessmentTimeGeneration, *)
    by Id
| extend UpperCamelCase = isnotempty(AdditionalData["AssessedResourceType"])
| extend
    Keys = iff(UpperCamelCase, dynamic(null), extract_all(@'(\"[^\"]+\"\:)', tostring(AdditionalData))),
    Initials = iff(UpperCamelCase, dynamic(null), extract_all(@'(\".)[^\"]*\"\:', tostring(AdditionalData)))
| extend AdditionalData = iff(UpperCamelCase,
    AdditionalData,
    todynamic(replace_strings(
        tostring(AdditionalData),
        Keys,
        todynamic(replace_strings(
            tostring(Keys),
            Initials,
            todynamic(toupper(Initials))
            ))
        ))
    )
| extend AssessedResourceType = tostring(AdditionalData["AssessedResourceType"])
| extend Scanner = case(
    AssessedResourceType == "ServerVulnerabilityTvm", "MDVM - Microsoft Defender Vulnerability Management",
    //AssessedResourceType == "ServerVulnerability", "Qualys",
    ""
    )
| where AssessedResourceType == "ServerVulnerabilityTvm" or (strlen(VulnerabilityId) == 6 and VulnerabilityId matches regex @"[A-Z0-9]*[A-Z][A-Z0-9]*")
| join hint.remote=local kind=leftouter (
    arg("").ResourceContainers
    | where type == "microsoft.resources/subscriptions"
    | project RecommendationSubscriptionId = subscriptionId, RecommendationSubscriptionName = name
    ) on RecommendationSubscriptionId
| project
    //TimeGenerated,
    StartSubAssessmentTimeGeneration,
    EndSubAssessmentTimeGeneration,
    Assessment_Age = bin(EndSubAssessmentTimeGeneration - StartSubAssessmentTimeGeneration, 1d)/1d,
    IsSnapshot,
    // ResourceProviderType,
    Scanner,
    Source = tostring(AdditionalData["Source"]),
    ParentRecommendationId,
    //NestedRecommendationId,
    RecommendationState,
    Cause,
    RecommendationSeverity,
    RecommendationSubscriptionId = coalesce(RecommendationSubscriptionName, RecommendationSubscriptionId),
    ResourceGroup,
    AssessedResourceId,
    RecommendationName,
    VulnerabilityId,
    Category,
    Description,
    //Impact, // Qualys
    //RemediationDescription, //Qualys
    //ResourceDetails,
    //Id,
    //AdditionalData,
    //AdditionalDataKeys = array_sort_asc(bag_keys(AdditionalData)),
    Cve = AdditionalData["Cve"],
    CurrentSoftwareName = AdditionalData["SoftwareName"],
    CurrentSoftwareVersion = AdditionalData["SoftwareVersion"],
    RecommendedSoftwareName = AdditionalData["RecommendedProgram"],
    RecommendedSoftwareVersion = AdditionalData["RecommendedVersion"],
    //AssessedResourceType,
    ResourceLocation = coalesce(AdditionalData["CloudSpecificEnrichmentData"]["AssessedResourceType"], ResourceDetails["Source"], ResourceDetails["source"]),
    ResourceHierarchyId = AdditionalData["CloudSpecificEnrichmentData"]["HierarchyId"],
    NativeCloudUniqueIdentifier = AdditionalData["CloudSpecificEnrichmentData"]["NativeCloudUniqueIdentifier"],
    ResourceType = AdditionalData["CloudSpecificEnrichmentData"]["ResourceType"]

Explanation

The query retrieves data from the SecurityNestedRecommendation table within a specified time period. It filters the data based on specific ParentRecommendationIds and Source values. It then summarizes the data by grouping it by Id and calculating the minimum and maximum values of a field called SubAssessmentTimeGeneration. It also performs some data manipulation and extraction operations. Finally, it joins the data with another table and selects specific columns for the output.

Details

Jose Sebastián Canós profile picture

Jose Sebastián Canós

Released: January 11, 2024

Tables

SecurityNestedRecommendation

Keywords

AssessedResourceType,Scanner,Source,ParentRecommendationId,RecommendationState,Cause,RecommendationSeverity,RecommendationSubscriptionId,ResourceGroup,AssessedResourceId,RecommendationName,VulnerabilityId,Category,Description,Cve,CurrentSoftwareName,CurrentSoftwareVersion,RecommendedSoftwareName,RecommendedSoftwareVersion,ResourceLocation,ResourceHierarchyId,NativeCloudUniqueIdentifier,ResourceType

Operators

whereandinsummarizehint.strategyminarg_maxbyextendisnotemptyextract_alliffdynamicreplace_stringstodynamictouppertostringcasejoinonprojectbincoalescearray_sort_asc

Actions