Query Details

Security Nested Recommendation Container Registries MDVM Vulnerability Assessments

Query

let query_period = 120d;
SecurityNestedRecommendation
| where TimeGenerated > ago(query_period) and ParentRecommendationId in ("c0b7cfc6-3172-465a-b378-53c7ff2cc0d5", "c27441ae-775c-45be-8ffa-655de37362ce")
| summarize hint.strategy=shuffle
    StartSubAssessmentTimeGeneration = min(SubAssessmentTimeGeneration),
    EndSubAssessmentTimeGeneration = arg_max(SubAssessmentTimeGeneration, *)
    by Id
| extend
    RegistryLocation = case(
        ParentRecommendationId == "c0b7cfc6-3172-465a-b378-53c7ff2cc0d5", "Azure",
        ParentRecommendationId == "c27441ae-775c-45be-8ffa-655de37362ce", "AWS",
        ""),
    Scanner = "MDVM - Microsoft Defender Vulnerability Management" // "c0b7cfc6-3172-465a-b378-53c7ff2cc0d5" "MDVM" "AzureContainerRegistryVulnerability"
// "dbd0cb49-b563-45e7-9724-889e799fa648" "Qualys"|"Trivy" "ContainerRegistryVulnerability"
// "03587042-5d4b-44ff-af42-ae99e3c71c87" "Trivy" "ContainerRegistryVulnerability"
// "c27441ae-775c-45be-8ffa-655de37362ce" "MVDM" ""
| extend UpperCamelCase = isnotempty(AdditionalData["AssessedResourceType"])
| extend Keys = iff(UpperCamelCase, dynamic(null), set_union(extract_all(@'(\"[^\"]+\"\:)', tostring(AdditionalData)), dynamic(null)))
| extend Initials = iff(UpperCamelCase, dynamic(null), extract_all(@'(\".)[^\"]*\"\:', tostring(Keys)))
| extend AdditionalData = iff(UpperCamelCase,
    AdditionalData,
    todynamic(replace_strings(
        tostring(AdditionalData),
        Keys,
        todynamic(replace_strings(
            tostring(Keys),
            Initials,
            todynamic(toupper(Initials))
            ))
        ))
    )
| join hint.remote=local kind=leftouter (
    arg("").ResourceContainers
    | where type == "microsoft.resources/subscriptions"
    | project RecommendationSubscriptionId = subscriptionId, RecommendationSubscriptionName = name
    ) on RecommendationSubscriptionId
| project
    //TimeGenerated,
    LastPushedToRegistry = todatetime(AdditionalData["ArtifactDetails"]["LastPushedToRegistryUTC"]),
    StartSubAssessmentTimeGeneration,
    EndSubAssessmentTimeGeneration,
    Assessment_Age = bin(EndSubAssessmentTimeGeneration - StartSubAssessmentTimeGeneration, 1d)/1d,
    //IsSnapshot,
    //ResourceProviderType,
    Scanner,
    //ParentRecommendationId,
    //NestedRecommendationId,
    RecommendationState,
    Cause,
    RecommendationSeverity,
    RecommendationSubscriptionId = coalesce(RecommendationSubscriptionName, RecommendationSubscriptionId),
    ResourceGroup,
    AssessedResourceId,
    RecommendationName,
    VulnerabilityId,
    //Category, // Qualys
    Description,
    //Impact, // Qualys
    RemediationDescription,
    //ResourceDetails,
    //Id,
    //AdditionalData,
    //AdditionalDataKeys = array_sort_asc(bag_keys(AdditionalData)),
    CveId = AdditionalData["VulnerabilityDetails"]["CveId"],
    Vulnerability_Severity = AdditionalData["VulnerabilityDetails"]["Severity"],
    Vulnerability_PublishedDate = todatetime(AdditionalData["VulnerabilityDetails"]["PublishedDate"]),
    Vulnerability_Age = bin(now() - todatetime(AdditionalData["VulnerabilityDetails"]["PublishedDate"]), 1d)/1d,
    Vulnerability_Cvss = case(
        isnotempty(AdditionalData["VulnerabilityDetails"]["Cvss"]["3.0"]), strcat(AdditionalData["VulnerabilityDetails"]["Cvss"]["3.0"]["Base"], " - ", AdditionalData["VulnerabilityDetails"]["Cvss"]["3.0"]["CvssVectorString"]),
        isnotempty(AdditionalData["VulnerabilityDetails"]["Cvss"]["2.0"]), strcat(AdditionalData["VulnerabilityDetails"]["Cvss"]["2.0"]["Base"], " - ", AdditionalData["VulnerabilityDetails"]["Cvss"]["2.0"]["CvssVectorString"]),
        ""),
    Exploit_IsInExploitKit = tobool(AdditionalData["VulnerabilityDetails"]["ExploitabilityAssessment"]["IsInExploitKit"]),
    Exploit_IsPubliclyDisclosed = tobool(AdditionalData["VulnerabilityDetails"]["ExploitabilityAssessment"]["ExploitStepsPublished"]),
    Exploit_IsVerified = tobool(AdditionalData["VulnerabilityDetails"]["ExploitabilityAssessment"]["ExploitStepsVerified"]),
    Exploit_Types = AdditionalData["VulnerabilityDetails"]["ExploitabilityAssessment"]["Types"],
    Exploit_Uris = AdditionalData["VulnerabilityDetails"]["ExploitabilityAssessment"]["ExploitUris"],
    SoftwareName = AdditionalData["SoftwareDetails"]["PackageName"],
    SoftwareCurrentVersion = AdditionalData["SoftwareDetails"]["Version"],
    SoftwareFixedVersion = AdditionalData["SoftwareDetails"]["FixedVersion"],
    //AssessedResourceType = AdditionalData["AssessedResourceType"],
    //ArtifactType = AdditionalData["ArtifactDetails"]["ArtifactType"], // == "ContainerImage"
    RegistryHost = AdditionalData["ArtifactDetails"]["RegistryHost"],
    RepositoryName = AdditionalData["ArtifactDetails"]["RepositoryName"],
    ImageDigest = AdditionalData["ArtifactDetails"]["Digest"],
    ImageTags = array_sort_asc(AdditionalData["ArtifactDetails"]["Tags"]),
    RegistryLocation,
    MediaType = AdditionalData["ArtifactDetails"]["MediaType"]

Explanation

This KQL (Kusto Query Language) query is designed to analyze security recommendations related to vulnerabilities in Azure and AWS environments over the past 120 days. Here's a simplified breakdown of what the query does:

  1. Define Time Period: It sets a time period of 120 days to look back from the current date.

  2. Filter Data: It filters the SecurityNestedRecommendation table to include only records generated within the last 120 days and with specific ParentRecommendationId values corresponding to Azure and AWS.

  3. Summarize Data: It summarizes the data by calculating the earliest and latest sub-assessment times for each unique Id.

  4. Extend Data: It adds new columns to the data:

    • RegistryLocation: Determines if the recommendation is related to Azure or AWS based on ParentRecommendationId.
    • Scanner: Sets the scanner type to "MDVM - Microsoft Defender Vulnerability Management".
    • UpperCamelCase, Keys, Initials, and AdditionalData: These are used to manipulate and format additional data fields.
  5. Join with Subscription Data: It performs a left outer join with another dataset to include subscription details like RecommendationSubscriptionId and RecommendationSubscriptionName.

  6. Project Relevant Columns: It selects and formats specific columns for the final output, including:

    • Vulnerability details such as CveId, Severity, PublishedDate, and Cvss scores.
    • Exploitability assessments like whether the vulnerability is in an exploit kit or publicly disclosed.
    • Software details such as SoftwareName, CurrentVersion, and FixedVersion.
    • Artifact details like RegistryHost, RepositoryName, ImageDigest, and ImageTags.
    • Other metadata like RegistryLocation, MediaType, and Assessment_Age.

The query essentially provides a detailed report on vulnerabilities, their assessments, and related metadata for specific Azure and AWS security recommendations over the past 120 days.

Details

Jose Sebastián Canós profile picture

Jose Sebastián Canós

Released: January 26, 2024

Tables

SecurityNestedRecommendation

Keywords

SecurityRecommendationsVulnerabilityManagementAzureAWSMicrosoftDefenderResourceContainersSubscriptionsArtifactDetailsExploitabilityAssessmentSoftware

Operators

letwhereinsummarizehint.strategyminarg_maxbyextendcase==isnotemptyiffdynamicset_unionextract_alltostringtodynamicreplace_stringstoupperjoinhint.remotekindonprojecttodatetimebinnowcoalescestrcattoboolarray_sort_asc

Actions

GitHub