Detection rules › Kusto

M2131_EventLogManagementPostureChanged_EL1

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

'This alert is desinged to monitor Azure policies aligned with the Maturity Model for Event Log Management (M-21-31) standard. The alert triggers when EL1 policy compliance falls below 70% within a 1 week timeframe.'

MITRE ATT&CK coverage

TacticTechniques
DiscoveryT1082 System Information Discovery

Rule body kusto

id: 036ce0a8-a1ff-4731-a078-02b3207fa4f3
name: M2131_EventLogManagementPostureChanged_EL1
description: |
  'This alert is desinged to monitor Azure policies aligned with the Maturity Model for Event Log Management (M-21-31) standard. The alert triggers when EL1 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("agent","extension","retention","logs encryption","collect","retained","log profile","CloudTrail","metric","AWS","GCP","DNS","Auditing","Flow","logging","usage"), "Event Logging (EL0)",
  iff(RecommendationDisplayName has_any("container registries","logic apps","Enhanced monitoring","IoT Hub","Event Hub","App Service", "Kubernetes","updates","email", "automation", "adaptive"), "Advanced Event Logging (EL3)",
  iff(RecommendationDisplayName has_any("signatures","CMK","CMEK","double encryption","managed key","KMS","container","Watcher"), "Intermediate Event Logging (EL2)",
  iff(RecommendationDisplayName has_any("Exploit Guard","endpoint protection","Antimalware","health","VPC","Defender","Vulnerabilities","vulnerability","diagnostic","Key","activity log alert",""), "Basic Event Logging (EL1)","Other"))))
  | summarize arg_max(TimeGenerated, *) by RecommendationDisplayName, AssessedResourceId, MaturityLevel
  | summarize Failed = countif(RecommendationState == "Unhealthy"), Passed = countif(RecommendationState == "Healthy"), Total = countif(RecommendationState == "Healthy" or RecommendationState == "Unhealthy") by MaturityLevel
  | extend PassedControls = (Passed/todouble(Total))*100
  | extend RemediationLink = strcat('https://portal.azure.com/#blade/Microsoft_Azure_Security/SecurityMenuBlade/22')
  | project MaturityLevel, Total, PassedControls, Passed, Failed, RemediationLink, LastObserved=now()
  | where MaturityLevel <> ''
  | where MaturityLevel == "Basic Event Logging (EL1)"
  | where PassedControls < 70 
  //Adjust Either FailedRatePercentage or PasedRatePercentage Thresholds within   Organizational Needs
  | 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("agent","extension","retention","logs encryption","collect","retained","log profile","CloudTrail","metric","AWS","GCP","DNS","Auditing","Flow","logging","usage"), "Event Logging (EL0)",
iff(RecommendationDisplayName has_any("container registries","logic apps","Enhanced monitoring","IoT Hub","Event Hub","App Service", "Kubernetes","updates","email", "automation", "adaptive"), "Advanced Event Logging (EL3)",
iff(RecommendationDisplayName has_any("signatures","CMK","CMEK","double encryption","managed key","KMS","container","Watcher"), "Intermediate Event Logging (EL2)",
iff(RecommendationDisplayName has_any("Exploit Guard","endpoint protection","Antimalware","health","VPC","Defender","Vulnerabilities","vulnerability","diagnostic","Key","activity log alert",""), "Basic Event Logging (EL1)","Other"))))
MaturityLevel =
if(RecommendationDisplayName contains "agent" or RecommendationDisplayName contains "extension" or RecommendationDisplayName contains "retention" or RecommendationDisplayName contains "logs encryption" or RecommendationDisplayName contains "collect" or RecommendationDisplayName contains "retained" or RecommendationDisplayName contains "log profile" or RecommendationDisplayName contains "CloudTrail" or RecommendationDisplayName contains "metric" or RecommendationDisplayName contains "AWS" or RecommendationDisplayName contains "GCP" or RecommendationDisplayName contains "DNS" or RecommendationDisplayName contains "Auditing" or RecommendationDisplayName contains "Flow" or RecommendationDisplayName contains "logging" or RecommendationDisplayName contains "usage")"Event Logging (EL0)"
elseiff((RecommendationDisplayName has_any ("container registries", "logic apps", "Enhanced monitoring", "IoT Hub", "Event Hub", "App Service", "Kubernetes", "updates", "email", "automation", "adaptive")), "Advanced Event Logging (EL3)", iff((RecommendationDisplayName has_any ("signatures", "CMK", "CMEK", "double encryption", "managed key", "KMS", "container", "Watcher")), "Intermediate Event Logging (EL2)", iff((RecommendationDisplayName has_any ("Exploit Guard", "endpoint protection", "Antimalware", "health", "VPC", "Defender", "Vulnerabilities", "vulnerability", "diagnostic", "Key", "activity log alert", "")), "Basic Event Logging (EL1)", "Other")))

Stage 4: summarize

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

Stage 5: summarize

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

Stage 6: extend

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

Stage 7: extend

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

Stage 8: project

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

Stage 9: where

| where MaturityLevel <> ''

Stage 10: where

| where MaturityLevel == "Basic Event Logging (EL1)"

Stage 11: where

| where PassedControls < 70

Stage 12: sort

| sort by PassedControls desc

Stage 13: 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
MaturityLeveleq
  • Basic Event Logging (EL1) 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
Failedproject
LastObservedproject
MaturityLevelproject
Passedproject
PassedControlsproject
RemediationLinkproject
Totalproject
URLCustomEntityextend