Detection rules › Kusto

Possible Resource-Based Constrained Delegation Abuse

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

This query identifies Active Directory computer objects modifications that allow an adversary to abuse the Resource-based constrained delegation. This query checks for event id 5136 that the Object Class field is "computer" and the LDAP Display Name is "msDS-AllowedToActOnBehalfOfOtherIdentity" which is an indicator of Resource-based constrained delegation. Ref: https://shenaniganslabs.io/2019/01/28/Wagging-the-Dog.html

MITRE ATT&CK coverage

TacticTechniques
Privilege EscalationT1134 Access Token Manipulation

Event coverage

Rule body kusto

id: 2937bc6b-7cda-4fba-b452-ea43ba8e835f
name:  Possible Resource-Based Constrained Delegation Abuse
description: |
  'This query identifies Active Directory computer objects modifications that allow an adversary to abuse the Resource-based constrained delegation. 
  This query checks for event id 5136 that the Object Class field is "computer" and the LDAP Display Name is "msDS-AllowedToActOnBehalfOfOtherIdentity" which is an indicator of Resource-based constrained delegation.
  Ref: https://shenaniganslabs.io/2019/01/28/Wagging-the-Dog.html'
severity: Medium
requiredDataConnectors:
  - connectorId: SecurityEvents
    dataTypes:
      - SecurityEvent
queryFrequency: 1h
queryPeriod: 1h
triggerOperator: gt
triggerThreshold: 0
tactics:
  - PrivilegeEscalation
relevantTechniques:
  - T1134
query: |
  SecurityEvent
  | where EventID == 5136 
  | parse EventData with * 'ObjectClass">' ObjectClass "<" *
  | parse EventData with * 'AttributeLDAPDisplayName">' AttributeLDAPDisplayName "<" *
  | where ObjectClass == "computer" and AttributeLDAPDisplayName == "msDS-AllowedToActOnBehalfOfOtherIdentity"
  | parse EventData with * 'ObjectDN">' ObjectDN "<" *
  | summarize StartTime = min(TimeGenerated), EndTime = max(TimeGenerated) by Computer, SubjectAccount, SubjectUserName, SubjectDomainName, SubjectUserSid, SubjectLogonId, ObjectDN, AttributeLDAPDisplayName
  | extend HostName = tostring(split(Computer, ".")[0]), DomainIndex = toint(indexof(Computer, '.'))
  | extend HostNameDomain = iff(DomainIndex != -1, substring(Computer, DomainIndex + 1), Computer)
  | project-away DomainIndex
entityMappings:
  - entityType: Account
    fieldMappings:
      - identifier: FullName
        columnName: SubjectAccount
      - identifier: Name
        columnName: SubjectUserName
      - identifier: NTDomain
        columnName: SubjectDomainName
  - entityType: Account
    fieldMappings:
      - identifier: Sid
        columnName: SubjectUserSid
  - entityType: Host
    fieldMappings:
      - identifier: FullName
        columnName: Computer
      - identifier: HostName
        columnName: HostName
      - identifier: DnsDomain
        columnName: HostNameDomain
version: 1.0.3
kind: Scheduled
metadata:
    source:
        kind: Community
    author:
        name: Vasileios Paschalidis
    support:
        tier: Community
    categories:
        domains: [ "Security - Others", "Identity" ]

Stages and Predicates

Stage 1: source

SecurityEvent

Stage 2: where

| where EventID == 5136

Stage 3: parse

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

Stage 4: parse

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

Stage 5: where

| where ObjectClass == "computer" and AttributeLDAPDisplayName == "msDS-AllowedToActOnBehalfOfOtherIdentity"

Stage 6: parse

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

Stage 7: summarize

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

Stage 8: extend

| extend HostName = tostring(split(Computer, ".")[0]), DomainIndex = toint(indexof(Computer, '.'))

Stage 9: extend

| extend HostNameDomain = iff(DomainIndex != -1, substring(Computer, DomainIndex + 1), Computer)
HostNameDomain =
ifDomainIndex != -1substring(Computer, (DomainIndex + 1))
elseComputer

Stage 10: project-away

| project-away DomainIndex

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
AttributeLDAPDisplayNameeq
  • msDS-AllowedToActOnBehalfOfOtherIdentity transforms: cased corpus 3 (sigma 2, kusto 1)
EventIDeq
  • 5136 transforms: cased corpus 30 (splunk 24, kusto 5, elastic 1)
ObjectClasseq
  • computer transforms: cased corpus 2 (sigma 1, kusto 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
AttributeLDAPDisplayNamesummarize
Computersummarize
EndTimesummarize
ObjectDNsummarize
StartTimesummarize
SubjectAccountsummarize
SubjectDomainNamesummarize
SubjectLogonIdsummarize
SubjectUserNamesummarize
SubjectUserSidsummarize
HostNameextend
HostNameDomainextend