Detection rules › Kusto

PROD (TM005.1) - GPO - Linked, Unlinked, or Enforced at Tier Level OU

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

Linking, Unlinking, or Enforcing of a GPO within the Tier Level OU structure

MITRE ATT&CK coverage

Telemetry coverage

Rule body

id: 02cf2172-0eb7-4a4a-bce7-7251cdd3e233
name: 'PROD (TM005.1) - GPO - Linked, Unlinked, or Enforced at Tier Level OU'
description: |
  Linking, Unlinking, or Enforcing of a GPO within the Tier Level OU structure
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)OU=Domain Controllers"
          or EventData matches regex @"(?i)OU=Tier 0 Member Servers"
          or EventData matches regex @"(?i)OU=Tier 1 Member Servers"
          or EventData matches regex @"(?i)OU=Tier 2 End-User Accounts"
          or EventData matches regex @"(?i)OU=Tier 2 End-User Devices"
          or EventData matches regex @"(?i)OU=Tier 2 End-User Groups"
          or EventData matches regex @"(?i)OU=Tier Model Administration"
          or EventData matches regex @"(?i)OU=Tier Model Computer Quarantine")
      and Activity has "modified" 
      and EventData has '"ObjectClass">organizationalUnit'
      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\">(((?i)OU=[^,]+,?)+),(?i)DC=", 1, EventData)
  | extend ObjectTier = case(
      ObjectName has "Tier 0", "Tier 0",
      ObjectName has "Tier 1", "Tier 1",
      ObjectName has "Tier 2", "Tier 2",
      ObjectName has "Tier Model Administration", "Tier 0",
      ObjectName has "Tier Model Computer Quarantine", "Tier 0",
      ObjectName has "Domain Controllers", "Tier 0",
      "Unknown")
  | 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: '(TM005.1) A GPO was {{ActivityType}} at the following {{ObjectTier}} {{ObjectName}} OU'
  alertDescriptionFormat: 'This will alert when a GPO is linked, unlinked, or enforced at any of the Tier Model OUs.'
version: 1.0.0
kind: Scheduled

Stages and Predicates

Stage 1: source

SecurityEvent

Stage 2: where

| where EventID == 5136 
    and (EventData matches regex @"(?i)OU=Domain Controllers"
        or EventData matches regex @"(?i)OU=Tier 0 Member Servers"
        or EventData matches regex @"(?i)OU=Tier 1 Member Servers"
        or EventData matches regex @"(?i)OU=Tier 2 End-User Accounts"
        or EventData matches regex @"(?i)OU=Tier 2 End-User Devices"
        or EventData matches regex @"(?i)OU=Tier 2 End-User Groups"
        or EventData matches regex @"(?i)OU=Tier Model Administration"
        or EventData matches regex @"(?i)OU=Tier Model Computer Quarantine")
    and Activity has "modified" 
    and EventData has '"ObjectClass">organizationalUnit'
    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 (8 consecutive steps)

| extend ObjectName = extract("<Data Name=\"ObjectDN\">(((?i)OU=[^,]+,?)+),(?i)DC=", 1, EventData)
| extend ObjectTier = case(
    ObjectName has "Tier 0", "Tier 0",
    ObjectName has "Tier 1", "Tier 1",
    ObjectName has "Tier 2", "Tier 2",
    ObjectName has "Tier Model Administration", "Tier 0",
    ObjectName has "Tier Model Computer Quarantine", "Tier 0",
    ObjectName has "Domain Controllers", "Tier 0",
    "Unknown")
| 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 4: 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">organizationalUnit transforms: term corpus 5 (kusto 5)
  • "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)OU=Domain Controllers corpus 8 (kusto 8)
  • (?i)OU=Tier 0 Member Servers corpus 8 (kusto 8)
  • (?i)OU=Tier 1 Member Servers corpus 8 (kusto 8)
  • (?i)OU=Tier 2 End-User Accounts corpus 3 (kusto 3)
  • (?i)OU=Tier 2 End-User Devices corpus 3 (kusto 3)
  • (?i)OU=Tier 2 End-User Groups corpus 3 (kusto 3)
  • (?i)OU=Tier Model Administration corpus 3 (kusto 3)
  • (?i)OU=Tier Model Computer Quarantine corpus 3 (kusto 3)
field:"EventData" kind:regex_match
EventIDeq
  • 5136 corpus 45 (splunk 24, kusto 18, elastic 3)
field:"EventID" kind:eq value:"5136"

Output fields

These fields are emitted when the rule matches.

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