Query Details
let query_period = 120d;
SecurityNestedRecommendation
| where TimeGenerated > ago(query_period) and ParentRecommendationId == "c609cf0f-71ab-41e9-a3c6-9a1f7fe1b8d5"
| summarize hint.strategy=shuffle
StartSubAssessmentTimeGeneration = min(SubAssessmentTimeGeneration),
EndSubAssessmentTimeGeneration = arg_max(SubAssessmentTimeGeneration, *)
by Id
| extend Scanner = "MDVM - Microsoft Defender Vulnerability Management" // AzureRuntimeImageVulnerability
//"41503391-efa5-47ee-9282-4eff6131462c" "Qualys" // GeneralVulnerability
| 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,
//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"]["IsPubliclyDisclosed"]),
Exploit_IsVerified = tobool(AdditionalData["VulnerabilityDetails"]["ExploitabilityAssessment"]["IsVerified"]),
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"]),
ClusterResourceId = AdditionalData["ClusterDetails"]["ClusterResourceId"],
KubernetesContext = AdditionalData["KubernetesContext"]
The query retrieves data from the SecurityNestedRecommendation table and filters it based on a specific time period and ParentRecommendationId. It then summarizes the data by grouping it by Id and calculates the minimum and maximum values of the SubAssessmentTimeGeneration field. The query also joins the data with the ResourceContainers table and projects specific columns from both tables. Finally, it projects various columns from the joined data, performs calculations on some columns, and renames some columns for better readability.

Jose Sebastián Canós
Released: December 29, 2023
Tables
Keywords
Operators