Detection rules › Kusto

AdminSDHolder Modifications

Severity
high
Time window
1h
Group by
Computer, ObjectDN, SubjectAccount, SubjectLogonId, SubjectUserSid
Author
Vasileios Paschalidis
Source
github.com/Azure/Azure-Sentinel

This query detects modification in the AdminSDHolder in the Active Directory which could indicate an attempt for persistence. AdminSDHolder Modification is a persistence technique in which an attacker abuses the SDProp process in Active Directory to establish a persistent backdoor to Active Directory. This query searches for the event id 5136 where the Object DN is AdminSDHolder. Ref: https://netwrix.com/en/cybersecurity-glossary/cyber-security-attacks/adminsdholder-attack/

MITRE ATT&CK coverage

TacticTechniques
PersistenceT1078 Valid Accounts

Event coverage

Rule body kusto

id: 52aec824-96c1-4a03-8e44-bb70532e6cea
name: AdminSDHolder Modifications
description: |
   'This query detects modification in the AdminSDHolder  in the Active Directory which could indicate an attempt for persistence. 
   AdminSDHolder Modification is a persistence technique in which an attacker abuses the SDProp process in Active Directory to establish a persistent backdoor to Active Directory.
   This query searches for the event id 5136 where the Object DN is AdminSDHolder.
   Ref: https://netwrix.com/en/cybersecurity-glossary/cyber-security-attacks/adminsdholder-attack/'
severity: High
requiredDataConnectors:
  - connectorId: SecurityEvents
    dataTypes:
      - SecurityEvent
queryFrequency: 1h
queryPeriod: 1h
triggerOperator: gt
triggerThreshold: 0
tactics:
  - Persistence
relevantTechniques:
  - T1078
query: |
   SecurityEvent
   | where EventID == 5136 and EventData contains "<Data Name=\"ObjectDN\">CN=AdminSDHolder,CN=System"
   | parse EventData with * 'ObjectDN">' ObjectDN "<" *
   | summarize StartTime = min(TimeGenerated), EndTime = max(TimeGenerated) by Computer, SubjectAccount, SubjectUserSid, SubjectLogonId, ObjectDN
   | extend HostName = tostring(split(Computer, ".")[0]), DomainIndex = toint(indexof(Computer, '.'))
   | extend HostNameDomain = iff(DomainIndex != -1, substring(Computer, DomainIndex + 1), Computer)
   | extend Name = tostring(split(SubjectAccount, "\\")[1]), NTDomain = tostring(split(SubjectAccount, "\\")[0])
entityMappings:
  - entityType: Account
    fieldMappings:
      - identifier: FullName
        columnName: SubjectAccount
      - identifier: Name
        columnName: Name
      - identifier: NTDomain
        columnName: NTDomain
  - entityType: Host
    fieldMappings:
      - identifier: FullName
        columnName: Computer
      - identifier: HostName
        columnName: HostName
      - identifier: DnsDomain
        columnName: HostNameDomain
version: 1.0.5
kind: Scheduled
metadata:
    source:
        kind: Community
    author:
        name: Vasileios Paschalidis
    support:
        tier: Community
    categories:
        domains: [ "Security - Others" ]

Stages and Predicates

Stage 1: source

SecurityEvent

Stage 2: where

| where EventID == 5136 and EventData contains "<Data Name=\"ObjectDN\">CN=AdminSDHolder,CN=System"

Stage 3: parse

| parse EventData with * 'ObjectDN">' ObjectDN "<" *

Stage 4: summarize

| summarize StartTime = min(TimeGenerated), EndTime = max(TimeGenerated) by Computer, SubjectAccount, SubjectUserSid, SubjectLogonId, ObjectDN

Stage 5: extend (3 consecutive steps)

| extend HostName = tostring(split(Computer, ".")[0]), DomainIndex = toint(indexof(Computer, '.'))
| extend HostNameDomain = iff(DomainIndex != -1, substring(Computer, DomainIndex + 1), Computer)
| extend Name = tostring(split(SubjectAccount, "\\")[1]), NTDomain = tostring(split(SubjectAccount, "\\")[0])

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
EventDatacontains
  • <Data Name=\"ObjectDN\">CN=AdminSDHolder,CN=System
EventIDeq
  • 5136 transforms: cased corpus 30 (splunk 24, kusto 5, elastic 1)

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
Computersummarize
EndTimesummarize
ObjectDNsummarize
StartTimesummarize
SubjectAccountsummarize
SubjectLogonIdsummarize
SubjectUserSidsummarize
DomainIndexextend
HostNameextend
HostNameDomainextend
NTDomainextend
Nameextend