Query Details

HUNT 17 AD Forest Trust Abuse Indicators 30d

Query

// =========================================================
// HUNT-17 | AD-ForestTrust-Abuse-Indicators-30d
// Description : Hunts for inter-forest / inter-domain
//               trust abuse patterns: anomalous cross-domain
//               TGT requests (4768 with foreign ClientAddress),
//               referral TGS tickets (4768/4769 for
//               inter-realm krbtgt), unusual domain-to-domain
//               authentication, and SID filtering disablement
//               indicators (EventID 4706, 4707).
// Period      : 30 days
// Use Case    : Forest trust abuse, SID history across
//               trusts, inter-realm Golden Ticket, trust
//               relationship modifications
// Tables      : SecurityEvent
// =========================================================

let Period = 30d;

// Known internal domain controllers (proxy via 4768 issuers)
let KnownDCs = SecurityEvent
    | where TimeGenerated > ago(Period)
    | where EventID == 4768
    | summarize by KnownDC = toupper(Computer);

// Trust creation and modification events
let TrustChanges = SecurityEvent
    | where TimeGenerated > ago(Period)
    | where EventID in (4706, 4707)   // 4706=new trust, 4707=trust removed
    | extend
        TrustType  = EventID,
        Actor      = strcat(SubjectDomainName, "\\", SubjectUserName),
        TrustedDom = TargetDomainName,
        EventType  = iff(EventID == 4706, "TrustCreated", "TrustRemoved");

// Cross-realm TGT / referral ticket requests
// These have a non-local domain suffix in TargetDomainName
let CrossRealmTGT = SecurityEvent
    | where TimeGenerated > ago(Period)
    | where EventID == 4768
    | where TargetDomainName !has Computer   // requester domain != issuing DC domain suffix
       and TargetDomainName !in~ ("", "-")
    | extend
        AccountNorm   = tolower(TargetUserName),
        SourceDomain  = TargetDomainName,
        SourceIP      = ClientAddress,
        IsForwardable = tostring(column_ifexists("TicketOptions", "")) has "0x40800000";  // Forwardable TGT

// Inter-realm TGS (referral path through krbtgt/<domain>)
let InterRealmTGS = SecurityEvent
    | where TimeGenerated > ago(Period)
    | where EventID == 4769
    | where ServiceName startswith "krbtgt/"   // cross-domain referral
    | extend
        RequesterNorm  = tolower(SubjectUserName),
        TargetRealm    = tostring(split(ServiceName, "/")[1]),
        EncType        = tostring(column_ifexists("TicketEncryptionType", "")),
        IsRC4          = tostring(column_ifexists("TicketEncryptionType", "")) == "0x17";  // RC4 inter-realm = suspicious

// Summarise cross-realm TGT requests
let CrossRealmSummary = CrossRealmTGT
    | summarize
        CrossRealmTGTCount  = count(),
        SourceDomains       = make_set(SourceDomain, 10),
        SourceIPs           = make_set(SourceIP, 10),
        ForwardableTickets  = countif(IsForwardable),
        LastSeen            = max(TimeGenerated)
      by AccountNorm;

// Summarise inter-realm TGS referrals
let InterRealmSummary = InterRealmTGS
    | summarize
        InterRealmCount  = count(),
        TargetRealms     = make_set(TargetRealm, 10),
        RC4InterRealm    = countif(IsRC4),
        LastReferral     = max(TimeGenerated)
      by RequesterNorm;

// Trust changes (always high risk)
TrustChanges
| summarize
    TrustChangeCount = count(),
    TrustEvents      = make_set(EventType, 5),
    TrustedDomains   = make_set(TrustedDom, 10),
    Actors           = make_set(Actor, 10),
    LastChange       = max(TimeGenerated)
  by Computer
| extend
    RiskLevel = "Critical - Trust_Relationship_Modified",
    RiskScore = TrustChangeCount * 100
| union (
    CrossRealmSummary
    | join kind=leftouter (InterRealmSummary)
        on $left.AccountNorm == $right.RequesterNorm
    | extend
        RiskScore = (CrossRealmTGTCount * 10)
                  + (iff(isnotnull(InterRealmCount), InterRealmCount * 15, 0))
                  + (iff(isnotnull(RC4InterRealm) and RC4InterRealm > 0, 30, 0))
                  + (ForwardableTickets * 20),
        RiskLevel = case(
            isnotnull(RC4InterRealm) and RC4InterRealm > 0 and ForwardableTickets > 0,
                "Critical - RC4_Forwardable_InterRealm_Ticket",
            isnotnull(RC4InterRealm) and RC4InterRealm > 0,
                "High - RC4_InterRealm_Referral",
            ForwardableTickets > 3,
                "High - Multiple_Forwardable_CrossRealm_TGTs",
            CrossRealmTGTCount > 10,
                "Medium - High_CrossRealm_TGT_Volume",
            "Low"
        ),
        TrustChangeCount = 0,
        LastChange       = LastSeen
    | project
        Computer     = "CrossRealm",
        TrustChangeCount,
        TrustEvents  = pack_array("CrossRealm"),
        TrustedDomains = SourceDomains,
        Actors       = pack_array(AccountNorm),
        LastChange,
        RiskLevel,
        RiskScore
)
| order by RiskScore desc

Explanation

This KQL query is designed to detect potential abuse of trust relationships between Active Directory forests or domains over the past 30 days. Here's a simplified breakdown of what the query does:

  1. Known Domain Controllers: It identifies known internal domain controllers by looking at specific security events (EventID 4768) where a Ticket Granting Ticket (TGT) is issued.

  2. Trust Changes: It checks for events indicating the creation or removal of trust relationships between domains (EventID 4706 for new trust and 4707 for trust removal). It captures details like who made the change, what type of change it was, and which domains were involved.

  3. Cross-Realm TGT Requests: It looks for unusual TGT requests that involve cross-domain interactions, specifically when the requesting domain is different from the issuing domain. It also checks if these tickets are forwardable, which can be a security concern.

  4. Inter-Realm TGS Referrals: It examines requests for Ticket Granting Service (TGS) tickets that involve cross-domain referrals, particularly those using the "krbtgt" service. It flags requests using the RC4 encryption type as suspicious.

  5. Summarization and Risk Assessment:

    • Trust Changes: Summarizes the trust changes and assigns a critical risk level if any are found, due to the high risk associated with modifying trust relationships.
    • Cross-Realm and Inter-Realm Activity: Summarizes the cross-realm TGT requests and inter-realm TGS referrals, calculating a risk score based on the volume and nature of the activity. It assigns risk levels ranging from low to critical based on specific criteria, such as the presence of RC4 encryption or multiple forwardable tickets.
  6. Output: The results are combined and sorted by risk score, highlighting the most critical potential security issues related to trust abuse in the Active Directory environment.

In essence, this query helps identify and prioritize potential security threats related to the misuse of trust relationships between domains, which could indicate unauthorized access or other malicious activities.

Details

David Alonso profile picture

David Alonso

Released: March 24, 2026

Tables

SecurityEvent

Keywords

SecurityEvent

Operators

letsummarizebytoupperwhereagoinextendstrcatiff!has!in~tolowertostringcolumn_ifexistsstartswithsplitcountmake_setcountifmaxjoinkind=leftouteroncaseisnotnulland>+projectpack_arrayorder bydesc

Actions