Query Details

HUNT 08 AD SID History Enabled Accounts Audit 90d

Query

// =========================================================
// HUNT-08 | AD-SIDHistory-Enabled-Accounts-Audit-90d
// Description : Identifies all accounts with a non-empty
//               sIDHistory attribute (4765 / 5136),
//               correlating with privileged group membership
//               to surface SID History injection paths and
//               inter-forest privilege escalation risks.
// Period      : 90 days
// Use Case    : SID History hygiene, privilege escalation
//               path discovery, forest trust abuse
// Tables      : SecurityEvent
// =========================================================

let Period = 90d;

// Privileged group membership baseline
let PrivGroupMembers = SecurityEvent
    | where TimeGenerated > ago(Period)
    | where EventID in (4728, 4732, 4756)
    | where TargetUserName has_any ("Domain Admins", "Enterprise Admins",
                                    "Schema Admins", "Administrators",
                                    "Group Policy Creator Owners",
                                    "Account Operators", "Backup Operators",
                                    "Server Operators", "DnsAdmins")
    | summarize PrivGroups = make_set(TargetUserName) by SubjectNorm = tolower(tostring(column_ifexists("MemberName", "")));

// SID History attribute write events
let SIDHistoryWrites = SecurityEvent
    | where TimeGenerated > ago(Period)
    | where EventID == 5136
    | where tostring(column_ifexists("AttributeLDAPDisplayName", "")) =~ "sIDHistory"
    | extend
        TargetDN    = ObjectName,
        GrantedBy   = strcat(SubjectDomainName, "\\", SubjectUserName),
        GrantedAt   = TimeGenerated,
        IsWrite     = OperationType == "%%14675",  // Value Added
        IsDelete    = OperationType == "%%14676";  // Value Deleted

// Account migration events (SID history during account migration)
let SIDHistoryMigration = SecurityEvent
    | where TimeGenerated > ago(Period)
    | where EventID == 4765
    | extend
        TargetDN    = TargetAccount,
        ChangedBy   = strcat(SubjectDomainName, "\\", SubjectUserName),
        OldSID      = tostring(column_ifexists("OldTargetUserName", "")),
        NewSID      = tostring(column_ifexists("NewTargetUserName", "")),
        EventType   = "SIDHistoryMigration";

// Combined SID history events
let Combined = SIDHistoryWrites
    | project
        EventTime   = GrantedAt,
        TargetDN,
        Actor       = GrantedBy,
        EventType   = iff(IsWrite, "SIDHistoryAdded", "SIDHistoryRemoved"),
        Computer,
        IsWrite
    | union (SIDHistoryMigration
        | project
            EventTime  = TimeGenerated,
            TargetDN,
            Actor      = ChangedBy,
            EventType,
            Computer,
            IsWrite    = true);

Combined
| where IsWrite  // focus on additions
| extend AccountNorm = tolower(extract(@"CN=([^,]+)", 1, TargetDN))
| join kind=leftouter (PrivGroupMembers) on $left.AccountNorm == $right.SubjectNorm
| summarize
    SIDHistoryEvents   = count(),
    LastWriteTime      = max(EventTime),
    FirstWriteTime     = min(EventTime),
    WritingActors      = make_set(Actor, 10),
    DCs                = make_set(Computer, 10),
    PrivGroupMemberhip = make_set(PrivGroups, 10)
    by TargetDN, AccountNorm
| extend
    HasPrivGroup        = array_length(PrivGroupMemberhip) > 0
    //  SID History + privileged group = high privilege escalation risk
| extend
    EscalationRisk = case(
        array_length(PrivGroupMemberhip) > 0, "Critical - Privileged_Account_With_SIDHistory",
        SIDHistoryEvents >= 3,               "High - Multiple_SID_History_Writes",
        SIDHistoryEvents >= 1,               "Medium - SID_History_Present",
        "Low"
    ),
    RiskScore = (SIDHistoryEvents * 10)
              + iff(HasPrivGroup, 50, 0)
| project
    TargetDN,
    EscalationRisk,
    RiskScore,
    SIDHistoryEvents,
    HasPrivGroup,
    PrivGroupMemberhip,
    FirstWriteTime,
    LastWriteTime,
    WritingActors
| order by RiskScore desc

Explanation

This query is designed to identify and assess the risk of accounts with a non-empty sIDHistory attribute over the past 90 days. It focuses on detecting potential security risks related to SID History, which can be used for privilege escalation and abuse in Active Directory environments. Here's a simplified breakdown of what the query does:

  1. Time Period: The query examines events from the last 90 days.

  2. Privileged Group Membership: It creates a baseline of accounts that are members of privileged groups, such as "Domain Admins" or "Enterprise Admins," by looking at specific security events (4728, 4732, 4756).

  3. SID History Events: It identifies events where the sIDHistory attribute was written (event ID 5136) or during account migrations (event ID 4765). These events are crucial because they can indicate changes to an account's SID History, which might be used for unauthorized access.

  4. Combining Events: The query combines the SID History write events and migration events into a single dataset, focusing on additions to SID History.

  5. Risk Assessment: For each account with SID History changes:

    • It checks if the account is part of any privileged groups.
    • It calculates the risk level based on the number of SID History events and whether the account is in a privileged group.
    • It assigns a risk score, giving higher scores to accounts with more events and those in privileged groups.
  6. Output: The query outputs a list of accounts with details such as:

    • Distinguished Name (TargetDN)
    • Escalation risk level (e.g., "Critical," "High," "Medium," "Low")
    • Risk score
    • Number of SID History events
    • Whether the account is in a privileged group
    • Membership in privileged groups
    • First and last times SID History was written
    • Actors who wrote the SID History
  7. Sorting: The results are sorted by risk score in descending order, highlighting the accounts with the highest potential risk first.

Overall, this query helps security teams identify accounts that might pose a risk due to SID History manipulation, especially those with elevated privileges, and prioritize them for further investigation.

Details

David Alonso profile picture

David Alonso

Released: March 24, 2026

Tables

SecurityEvent

Keywords

SecurityEvent

Operators

letwhereinhas_anysummarizemake_setbytolowertostringcolumn_ifexists===~extendstrcatprojectiffunionjoinkind=leftouteroncountmaxminarray_lengthcase>=order bydesc

Actions