Query Details

RULE 24 AD Disabled Account Reactivated

Query

// =========================================================
// RULE-24 | AD-Disabled-Account-Reactivated
// Description : "Walking Dead" — Disabled privileged account
//               re-enabled. Event 4722 (User Account Enabled)
//               for an account that previously held membership
//               in a high-privilege group (Domain Admins,
//               Enterprise Admins, Backup Operators, etc.)
//               within the last 30 days.
//               Disabled accounts retain all their group
//               memberships, ACLs, SPNs, and attributes.
//               Re-enabling them instantly restores all
//               accumulated privileges — making them a stealthy
//               persistence and escalation vector.
// Severity    : High → Critical (DA/EA account re-enabled)
// Frequency   : Every 15 minutes, look-back 15 minutes
// MITRE       : T1098 — Account Manipulation
//               T1078  — Valid Accounts
// Tables      : SecurityEvent
// =========================================================

let LookBack = 15m;

// Groups that make an account "privileged"
let PrivilegedGroups = dynamic([
    "Domain Admins", "Enterprise Admins", "Schema Admins",
    "Administrators", "Backup Operators", "Server Operators",
    "Account Operators", "DnsAdmins", "Group Policy Creator Owners",
    "Remote Desktop Users", "Network Configuration Operators",
    "Cert Publishers"
]);

// Recent membership in privileged groups (last 30 days)
let RecentPrivilegedMembers = SecurityEvent
    | where TimeGenerated > ago(30d)
    | where EventID in (4728, 4732, 4756)
    | where TargetUserName has_any (PrivilegedGroups)
    | summarize
        GroupMemberships = make_set(TargetUserName, 10),
        IsTierZero = anyif(true,
            TargetUserName has_any ("Domain Admins", "Enterprise Admins",
                                    "Schema Admins", "Administrators"))
        by PrivMember = tolower(MemberName);

// Accounts re-enabled in the detection window
SecurityEvent
| where TimeGenerated > ago(LookBack)
| where EventID == 4722                         // User Account Enabled
| extend
    ReenabledAccount = tolower(TargetUserName),
    ReenabledBy      = strcat(SubjectDomainName, "\\", SubjectUserName)
| join kind=inner (RecentPrivilegedMembers)
    on $left.ReenabledAccount == $right.PrivMember
| extend
    Severity = case(
        IsTierZero, "Critical",
        "High"
    ),
    WhySuspicious = strcat(
        "Disabled_Privileged_Account_Reenabled; ",
        iff(IsTierZero, "WAS_DA_EA_SA_Critical; ", ""),
        "Account: ", TargetUserName, "; ",
        "PreviousGroups: ", strcat_array(GroupMemberships, ", "), "; ",
        "ReenabledBy: ", ReenabledBy
    )
| project
    TimeGenerated,
    Severity,
    WhySuspicious,
    ReenabledAccount = TargetUserName,
    ReenabledBy,
    GroupMemberships,
    IsTierZero,
    Computer,
    SubjectUserName,
    SubjectDomainName
| order by Severity asc, TimeGenerated desc

Explanation

This query is designed to detect and alert on the reactivation of previously disabled privileged user accounts in an Active Directory environment. Here's a simple breakdown of what it does:

  1. Purpose: The query identifies when a previously disabled account, which was part of high-privilege groups (like Domain Admins or Enterprise Admins) within the last 30 days, is re-enabled. This is considered a security risk because re-enabling such accounts restores all their privileges, potentially allowing unauthorized access or actions.

  2. Frequency: The query runs every 15 minutes, checking for events in the last 15 minutes.

  3. Privileged Groups: It defines a list of groups that are considered privileged, such as "Domain Admins" and "Backup Operators".

  4. Recent Membership Check: It looks back 30 days to find accounts that were members of these privileged groups.

  5. Re-enabled Accounts: It then checks for accounts that have been re-enabled (Event ID 4722) within the last 15 minutes.

  6. Join and Analysis: The query joins the re-enabled accounts with the list of recently privileged accounts to identify matches.

  7. Severity and Suspicion: If the re-enabled account was part of critical groups like "Domain Admins", the severity is marked as "Critical"; otherwise, it's "High". It also constructs a message explaining why the account reactivation is suspicious.

  8. Output: The query outputs details such as the time of the event, severity, reasons for suspicion, the account re-enabled, who re-enabled it, and the account's previous group memberships.

Overall, this query helps in identifying potential security threats by monitoring the reactivation of privileged accounts, which could be a sign of unauthorized access or escalation attempts.

Details

David Alonso profile picture

David Alonso

Released: March 24, 2026

Tables

SecurityEvent

Keywords

SecurityEventDevicesUserAccountPrivilegedGroupsDomainAdminsEnterpriseSchemaAdministratorsBackupOperatorsServerDnsAdminsGroupPolicyCreatorOwnersRemoteDesktopUsersNetworkConfigurationCertPublishersMemberNameTargetUserNameSubjectDomainNameSubjectUserNameComputer

Operators

letdynamicagoinhas_anysummarizemake_setanyiftolowerwhereextendstrcatjoinoncaseiffprojectorder byascdesc

MITRE Techniques

Actions

GitHub