Detection rules › Kusto

PROD (TM008.1) - GPO - Linked, Unlinked, or Enforced at Root of Domain

Status
available
Severity
high
Time window
5m
Source
github.com/Azure/Azure-Sentinel

Linked, Unlinked, or Enforced GPOs at the Root of the Domain which could overwrite Tier Model GPOs.

MITRE ATT&CK coverage

Telemetry coverage

Rule body

id: fe468726-b1dc-4e76-adad-3480de4a2c56
name: 'PROD (TM008.1) - GPO - Linked, Unlinked, or Enforced at Root of Domain'
description: |
  Linked, Unlinked, or Enforced GPOs at the Root of the Domain which could overwrite Tier Model GPOs.
severity: High
requiredDataConnectors:
  - connectorId: SecurityEvents
    dataTypes:
      - SecurityEvent
  - connectorId: WindowsSecurityEvents
    dataTypes:
      - SecurityEvent
queryFrequency: 5m
queryPeriod: 5m
triggerOperator: gt
triggerThreshold: 0
status: Available
tactics:
  - DefenseEvasion
relevantTechniques:
  - T1484.001
query: |
  SecurityEvent 
  | where EventID == 5136 
      and EventData matches regex @"(?i)DC="
      and Activity has "modified" 
      and EventData has '"ObjectClass">domainDNS'
      and EventData has '<Data Name="AttributeLDAPDisplayName">gPLink</Data>' 
      and (EventData has ';0]' 
          or EventData has ';1]' 
          or EventData has ';2]')
      and EventData has '"OperationType">%%14674'
  | extend ObjectName = extract("<Data Name=\"ObjectDN\">([^<]+)</Data>", 1, EventData)
  | where ObjectName startswith "DC=" or ObjectName startswith "dc="
  | extend ObjectTier = "Tier 0"
  | extend AttributeLDAP = extract("<Data Name=\"AttributeLDAPDisplayName\">([^<]+)</Data>", 1, EventData)
  | extend AttributeValue = extract("\\[([^\\]]+)\\]", 1, EventData)
  | extend LastThreeChars = substring(AttributeValue, strlen(AttributeValue) - 2, 3)
  | extend AttributeValueDescription = case(
      LastThreeChars == ";0", "Linked",
      LastThreeChars == ";1", "Unlinked",
      LastThreeChars == ";2", "Enforced",
      "Unknown")
  | extend ObjectClass = extract("<Data Name=\"ObjectClass\">([^<]+)</Data>", 1, EventData)
  | extend Domain = extract("([^.]+\\.[^.]+)$", 1, Computer)
  | project TimeGenerated
     , ObjectName
     , ObjectTier
     , ObjectClass
     , ActivityType = AttributeValueDescription
     , AttributeLDAP
     , Account
     , Domain
     , Computer
     , Channel
     , EventID
     , EventData
entityMappings:
  - entityType: Account
    fieldMappings:
      - identifier: FullName
        columnName: ObjectName
  - entityType: Host
    fieldMappings:
      - identifier: HostName
        columnName: Computer
  - entityType: Account
    fieldMappings:
      - identifier: FullName
        columnName: Account
customDetails:
  ObjectName: ObjectName
  ObjectTier: ObjectTier
  ObjectClass: ObjectClass
  ActivityType: ActivityType
  AttributeLDAP: AttributeLDAP
  Account: Account
  Domain: Domain
  Computer: Computer
  Channel: Channel
  EventID: EventID
  EventData: EventData
eventGroupingSettings:
  aggregationKind: AlertPerResult
incidentConfiguration:
  createIncident: true
  groupingConfiguration:
    enabled: false
    reopenClosedIncident: false
    lookbackDuration: PT5H
    matchingMethod: AllEntities
alertDetailsOverride:
  alertDisplayNameFormat: '(TM008.1) A Tier 0 GPO was {{ActivityType}} at the Root of the Domain'
  alertDescriptionFormat: 'Changes to the Root of the Domain GPO could impact the Tier Model GPOs and other security controls.'
version: 1.0.0
kind: Scheduled

Stages and Predicates

Stage 1: source

SecurityEvent

Stage 2: where

| where EventID == 5136 
    and EventData matches regex @"(?i)DC="
    and Activity has "modified" 
    and EventData has '"ObjectClass">domainDNS'
    and EventData has '<Data Name="AttributeLDAPDisplayName">gPLink</Data>' 
    and (EventData has ';0]' 
        or EventData has ';1]' 
        or EventData has ';2]')
    and EventData has '"OperationType">%%14674'

Stage 3: extend

| extend ObjectName = extract("<Data Name=\"ObjectDN\">([^<]+)</Data>", 1, EventData)

Stage 4: where

| where ObjectName startswith "DC=" or ObjectName startswith "dc="

Stage 5: extend (7 consecutive steps)

| extend ObjectTier = "Tier 0"
| extend AttributeLDAP = extract("<Data Name=\"AttributeLDAPDisplayName\">([^<]+)</Data>", 1, EventData)
| extend AttributeValue = extract("\\[([^\\]]+)\\]", 1, EventData)
| extend LastThreeChars = substring(AttributeValue, strlen(AttributeValue) - 2, 3)
| extend AttributeValueDescription = case(
    LastThreeChars == ";0", "Linked",
    LastThreeChars == ";1", "Unlinked",
    LastThreeChars == ";2", "Enforced",
    "Unknown")
| extend ObjectClass = extract("<Data Name=\"ObjectClass\">([^<]+)</Data>", 1, EventData)
| extend Domain = extract("([^.]+\\.[^.]+)$", 1, Computer)

Stage 6: project

| project TimeGenerated
   , ObjectName
   , ObjectTier
   , ObjectClass
   , ActivityType = AttributeValueDescription
   , AttributeLDAP
   , Account
   , Domain
   , Computer
   , Channel
   , EventID
   , EventData

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
Activitymatch
  • modified transforms: term corpus 10 (kusto 10)
field:"Activity" kind:match value:"modified"
EventDatamatch
  • "ObjectClass">domainDNS transforms: term corpus 2 (kusto 2)
  • "OperationType">%%14674 transforms: term corpus 7 (kusto 7)
  • ;0] transforms: term corpus 4 (kusto 4)
  • ;1] transforms: term corpus 4 (kusto 4)
  • ;2] transforms: term corpus 4 (kusto 4)
  • <Data Name="AttributeLDAPDisplayName">gPLink</Data> transforms: term corpus 4 (kusto 4)
field:"EventData" kind:match
EventDataregex_match
  • (?i)DC= corpus 2 (kusto 2)
field:"EventData" kind:regex_match value:"(?i)DC="
EventIDeq
  • 5136 corpus 45 (splunk 24, kusto 18, elastic 3)
field:"EventID" kind:eq value:"5136"
ObjectNamestarts_with
  • DC= corpus 4 (sigma 2, kusto 2)
  • dc= corpus 2 (kusto 2)
field:"ObjectName" kind:starts_with

Output fields

These fields are emitted when the rule matches.

FieldSource
Accountproject
ActivityTypeproject
AttributeLDAPproject
Channelproject
Computerproject
Domainproject
EventDataproject
EventIDproject
ObjectClassproject
ObjectNameproject
ObjectTierproject
TimeGeneratedproject