Detection rules › Kusto

CDM_ContinuousDiagnostics&Mitigation_PostureChanged

Status
available
Severity
medium
Time window
7d
Group by
AssessedResourceId, MaturityLevel, RecommendationDisplayName
Source
github.com/Azure/Azure-Sentinel

'This alert is designed to monitor Azure policies aligned with the Continuous Diagnostics & Mitigation (CDM) Program. The alert triggers when policy compliance falls below 70% within a 1 week timeframe.'

MITRE ATT&CK coverage

TacticTechniques
DiscoveryT1082 System Information Discovery

Rule body kusto

id: fd950af9-d9db-4879-a60a-7267cc041beb
name: CDM_ContinuousDiagnostics&Mitigation_PostureChanged
description: |
  'This alert is designed to monitor Azure policies aligned with the Continuous Diagnostics & Mitigation (CDM) Program. The alert triggers when policy compliance falls below 70% within a 1 week timeframe.'
severity: Medium
status: Available 
requiredDataConnectors: []
queryFrequency: 7d
queryPeriod: 7d
triggerOperator: gt
triggerThreshold: 0
tactics:
  - Discovery
relevantTechniques:
  - T1082
query: |
  SecurityRecommendation
  | where RecommendationDisplayName <> ""
  | extend MaturityLevel=iff(RecommendationDisplayName has_any("log", "defender", "asset", "arc"), "Hardware Asset Management (HWAM)",
      iff(RecommendationDisplayName has_any("allow", "software", "application"), "Software Asset Management (SWAM)",
      iff(RecommendationDisplayName has_any("account", "user", "identity", "trust"), "User Trust (TRUST)",
      iff(RecommendationDisplayName has_any("access", "auth", "key", "cert", "token"), "Credentials & Authenticators (CRED)",
      iff(RecommendationDisplayName has_any("priv", "admin", "root"), "Privileges (PRIV)",
      iff(RecommendationDisplayName has_any("network", "internet", "traffic", "firewall", "intrusion", "bound", "tls", "gateway", "subnet", "web", "url", "proxy", "just", "port", "JIT", "http"), "Boundary Protection (BOUND)",
      iff(RecommendationDisplayName has_any("event", "agent", "incident", "back", "privacy", "audit", "collect"), "Manage Events (MNGEVT)",
      iff(RecommendationDisplayName has_any("edr", "malware", "endpoint protection", "detect", "respon"), "Endpoint Detection & Response (EDR)",
      iff(RecommendationDisplayName has_any("aks", "contain", "kube", "supply"), "Design & Build in Security (DBS)",
      iff(RecommendationDisplayName has_any("data", "storage", "sql", "cmk", "key"), "Data Protection Management (DPM)", "Other"))))))))))
  | where MaturityLevel in ('Hardware Asset Management (HWAM)', 'Software Asset Management (SWAM)', 'User Trust (TRUST)', 'Credentials & Authenticators (CRED)', 'Privileges (PRIV)', 'Boundary Protection (BOUND)', 'Manage Events (MNGEVT)', 'Endpoint Detection & Response (EDR)', 'Design & Build in Security (DBS)', 'Data Protection Management (DPM)')
  | summarize arg_max(TimeGenerated, *) by AssessedResourceId, RecommendationDisplayName
  | summarize
      Failed = countif(RecommendationState == "Unhealthy"),
      Passed = countif(RecommendationState == "Healthy"),
      NotApplicable = countif(RecommendationState == "NotApplicable" or RecommendationState == "Removed"),
      Applicable = countif(RecommendationState == "Unhealthy" or RecommendationState == "Healthy"),
      Total = countif(RecommendationState == "Unhealthy" or RecommendationState == "Healthy" or RecommendationState == "NotApplicable" or RecommendationState == "Removed")
      by MaturityLevel
  | extend PassedControls = (Passed / todouble(Applicable)) * 100
  | project MaturityLevel, Total, PassedControls, Passed, Failed, Applicable, NotApplicable
  | sort by Total, Passed desc
  | extend RemediationLink = strcat('https://portal.azure.com/#blade/Microsoft_Azure_Security/SecurityMenuBlade/22')
  | project CapabilityArea=MaturityLevel, Total, PassedControls, Passed, Failed, RemediationLink, LastObserved=now()
  | where CapabilityArea <> ''
  | where PassedControls < 70 
  //Adjust Either FailedRatePercentage or PassedRatePercentage Thresholds within organizational requirements
  | sort by PassedControls desc
  | extend URLCustomEntity = RemediationLink
entityMappings:
  - entityType: URL
    fieldMappings:
      - identifier: Url
        columnName: URLCustomEntity
version: 1.0.0
kind: Scheduled

Stages and Predicates

Stage 1: source

SecurityRecommendation

Stage 2: where

| where RecommendationDisplayName <> ""

Stage 3: extend

| extend MaturityLevel=iff(RecommendationDisplayName has_any("log", "defender", "asset", "arc"), "Hardware Asset Management (HWAM)",
    iff(RecommendationDisplayName has_any("allow", "software", "application"), "Software Asset Management (SWAM)",
    iff(RecommendationDisplayName has_any("account", "user", "identity", "trust"), "User Trust (TRUST)",
    iff(RecommendationDisplayName has_any("access", "auth", "key", "cert", "token"), "Credentials & Authenticators (CRED)",
    iff(RecommendationDisplayName has_any("priv", "admin", "root"), "Privileges (PRIV)",
    iff(RecommendationDisplayName has_any("network", "internet", "traffic", "firewall", "intrusion", "bound", "tls", "gateway", "subnet", "web", "url", "proxy", "just", "port", "JIT", "http"), "Boundary Protection (BOUND)",
    iff(RecommendationDisplayName has_any("event", "agent", "incident", "back", "privacy", "audit", "collect"), "Manage Events (MNGEVT)",
    iff(RecommendationDisplayName has_any("edr", "malware", "endpoint protection", "detect", "respon"), "Endpoint Detection & Response (EDR)",
    iff(RecommendationDisplayName has_any("aks", "contain", "kube", "supply"), "Design & Build in Security (DBS)",
    iff(RecommendationDisplayName has_any("data", "storage", "sql", "cmk", "key"), "Data Protection Management (DPM)", "Other"))))))))))
MaturityLevel =
if(RecommendationDisplayName contains "log" or RecommendationDisplayName contains "defender" or RecommendationDisplayName contains "asset" or RecommendationDisplayName contains "arc")"Hardware Asset Management (HWAM)"
elseiff((RecommendationDisplayName has_any ("allow", "software", "application")), "Software Asset Management (SWAM)", iff((RecommendationDisplayName has_any ("account", "user", "identity", "trust")), "User Trust (TRUST)", iff((RecommendationDisplayName has_any ("access", "auth", "key", "cert", "token")), "Credentials & Authenticators (CRED)", iff((RecommendationDisplayName has_any ("priv", "admin", "root")), "Privileges (PRIV)", iff((RecommendationDisplayName has_any ("network", "internet", "traffic", "firewall", "intrusion", "bound", "tls", "gateway", "subnet", "web", "url", "proxy", "just", "port", "JIT", "http")), "Boundary Protection (BOUND)", iff((RecommendationDisplayName has_any ("event", "agent", "incident", "back", "privacy", "audit", "collect")), "Manage Events (MNGEVT)", iff((RecommendationDisplayName has_any ("edr", "malware", "endpoint protection", "detect", "respon")), "Endpoint Detection & Response (EDR)", iff((RecommendationDisplayName has_any ("aks", "contain", "kube", "supply")), "Design & Build in Security (DBS)", iff((RecommendationDisplayName has_any ("data", "storage", "sql", "cmk", "key")), "Data Protection Management (DPM)", "Other")))))))))

Stage 4: where

| where MaturityLevel in ('Hardware Asset Management (HWAM)', 'Software Asset Management (SWAM)', 'User Trust (TRUST)', 'Credentials & Authenticators (CRED)', 'Privileges (PRIV)', 'Boundary Protection (BOUND)', 'Manage Events (MNGEVT)', 'Endpoint Detection & Response (EDR)', 'Design & Build in Security (DBS)', 'Data Protection Management (DPM)')

Stage 5: summarize

| summarize arg_max(TimeGenerated, *) by AssessedResourceId, RecommendationDisplayName

Stage 6: summarize

| summarize
    Failed = countif(RecommendationState == "Unhealthy"),
    Passed = countif(RecommendationState == "Healthy"),
    NotApplicable = countif(RecommendationState == "NotApplicable" or RecommendationState == "Removed"),
    Applicable = countif(RecommendationState == "Unhealthy" or RecommendationState == "Healthy"),
    Total = countif(RecommendationState == "Unhealthy" or RecommendationState == "Healthy" or RecommendationState == "NotApplicable" or RecommendationState == "Removed")
    by MaturityLevel

Stage 7: extend

| extend PassedControls = (Passed / todouble(Applicable)) * 100

Stage 8: project

| project MaturityLevel, Total, PassedControls, Passed, Failed, Applicable, NotApplicable

Stage 9: sort

| sort by Total, Passed desc

Stage 10: extend

| extend RemediationLink = strcat('https://portal.azure.com/#blade/Microsoft_Azure_Security/SecurityMenuBlade/22')

Stage 11: project

| project CapabilityArea=MaturityLevel, Total, PassedControls, Passed, Failed, RemediationLink, LastObserved=now()

Stage 12: where

| where CapabilityArea <> ''

Stage 13: where

| where PassedControls < 70

Stage 14: sort

| sort by PassedControls desc

Stage 15: extend

| extend URLCustomEntity = RemediationLink

Indicators

Each row is a field, operator, and value that the rule matches. The corpus column counts how many other rules in the catalog look for the same combination: high numbers point to widely-used, community-vetted indicators. Blank or 1 shows that the indicator is specific to this rule.

FieldKindValues
MaturityLevelin
  • Boundary Protection (BOUND) transforms: cased
  • Credentials & Authenticators (CRED) transforms: cased
  • Data Protection Management (DPM) transforms: cased
  • Design & Build in Security (DBS) transforms: cased
  • Endpoint Detection & Response (EDR) transforms: cased
  • Hardware Asset Management (HWAM) transforms: cased
  • Manage Events (MNGEVT) transforms: cased
  • Privileges (PRIV) transforms: cased
  • Software Asset Management (SWAM) transforms: cased
  • User Trust (TRUST) transforms: cased
PassedControlslt
  • 70 transforms: cased

Output fields

Fields the rule emits when it matches. Chronicle authors list these in the outcome block; they appear on the detection and $risk_score drives alerting. Sentinel / Defender XDR rules build them up through project / summarize / extend stages. Sentinel maps these into alert fields via entityMappings and customDetails; Defender XDR custom detections surface them as alert fields directly.

FieldSource
CapabilityAreaproject
Failedproject
LastObservedproject
Passedproject
PassedControlsproject
RemediationLinkproject
Totalproject
URLCustomEntityextend