What Is Protection for Active Directory Privileged Accounts (Protected Users and Delegation)
Domain Admins, Enterprise Admins, and other Tier 0 accounts are the accounts an attacker needs to fully compromise a domain. For Active Directory privileged accounts, three built-in, independent controls do most of the real protection work: membership in the Protected Users security group, the "account is sensitive and cannot be delegated" delegation flag, and the basic hygiene rule that service accounts do not belong in privileged groups. On top of that, the SID History attribute — meant for domain migrations — can silently grant privileged access if it is never audited.
None of these are exotic. They are default, built-in AD features. The gap this article covers isn't a missing patch or a zero-day — it's these controls simply not being turned on for the accounts that need them, which is why it keeps showing up in Active Directory security assessments as a top offender. Each gap below is independently exploitable, and none require memory-resident tooling or process injection: they're attribute-level misconfigurations, visible to anyone who queries the directory the right way.
⚠️ Warning: These four gaps are additive. An account that is not in Protected Users, not marked non-delegable, AND carries stale SID History is not "somewhat exposed" three times — it is exposed to three unrelated attack techniques at once, each with its own detection surface.
How It Works
Protected Users: built but unused
The Protected Users global security group, introduced in Windows Server 2012 R2, applies non-configurable protections to any account added to it. Per Microsoft's Protected Users documentation, members cannot authenticate with NTLM, cannot use DES or RC4 for Kerberos pre-authentication, cannot be delegated with constrained or unconstrained delegation, and get a hard 4-hour Kerberos TGT lifetime with no renewal. Membership alone does the work — there is no policy to misconfigure once an account is in the group.
The catch is that most environments never populate it. Domain Admins and other Tier 0 accounts keep authenticating with legacy protocols and caching credentials in LSASS exactly as if the group didn't exist, because nobody added them to it.
ℹ️ Note: Protected Users is for human privileged accounts only. Microsoft explicitly warns that service and computer accounts should not be members — the group disables NTLM and credential caching that many services depend on, and it provides no local protection anyway, since the secret still has to live on the host running the service.
The "sensitive and cannot be delegated" flag
Separately from Protected Users, every AD account has a userAccountControl bit — NOT_DELEGATED (0x100000 / 1048576) — exposed in the GUI as "This account is sensitive and cannot be delegated." When set, the account's Kerberos ticket cannot be forwarded to a service configured for delegation, even if that service is otherwise trusted for delegation. According to Microsoft Defender for Identity's security assessment for this control, leaving it unset on privileged accounts means a compromised or malicious delegation-trusted service can request and reuse that account's ticket to impersonate it elsewhere on the network — an escalation path independent of whether the account is in Protected Users.
Delegation exposure on the account itself
Beyond the sensitive flag, an account can directly carry delegation configuration: TRUSTED_FOR_DELEGATION (unconstrained), msDS-AllowedToDelegateTo (constrained), or resource-based constrained delegation via msDS-AllowedToActOnBehalfOfOtherIdentity. Any of these on a Tier 0 account means a compromised delegation-trusted service can request tickets as that account. We cover exploitation of these mechanisms in depth in Kerberos Delegation Attacks: From Unconstrained to RBCD Abuse — the point for this article is narrower: a sensitive account should never be a delegation target in the first place, regardless of the attack technique used against it.
Service accounts sitting in privileged groups
A service account with a Service Principal Name (SPN) is Kerberoastable by design — any authenticated domain user can request a service ticket for it and attempt to crack the ticket offline (see our Kerberoasting guide for that attack chain). That risk is tolerable when the account only has access to the service it runs. It stops being tolerable the moment the account is also a member of Domain Admins or Enterprise Admins.
Microsoft's guidance on reducing membership in highly privileged administrative groups is explicit: privileged groups should be kept empty or limited to a small number of accountable administrators, and service accounts should receive narrow, delegated permissions instead of blanket Domain Admin rights. A service account in Domain Admins combines a crackable password with domain-wide privilege — everyone who can query SPNs already has a path to attempt full domain compromise.
SID History: the quiet fourth path
The sIDHistory attribute exists to preserve access during inter-domain migrations — a migrated user keeps the SID of their old account, appended to their token, so existing permissions keep working. Per MITRE ATT&CK T1134.005, an attacker with Domain Admin-equivalent rights (or DCSync capability) can insert a harvested or well-known privileged SID — such as Enterprise Admins' — into a low-privilege account's SID History. That account's token then carries Enterprise Admin rights without ever appearing as a member of the Enterprise Admins group, which is exactly what makes it dangerous: group-membership review misses it entirely.
Why Attackers Chain These Gaps Together
None of these four issues need to stand alone to be useful to an attacker, and in practice they rarely do. A privileged account without the sensitive flag is a viable delegation target; the same account outside Protected Users can still authenticate with NTLM, so an attacker with a relayed hash doesn't even need Kerberos. If that same environment also has a service account sitting in Domain Admins, an attacker who Kerberoasts and cracks its password gets a second, independent route to the same privilege tier — no delegation abuse required. And SID History gives a persistence option that survives a credential rotation on the original privileged account entirely, since the injected SID rides along on a completely different, low-privilege identity.
This is also why the gap is distinct from stale privileged accounts (dormant credentials nobody disabled — see Stale Privileged Accounts: Hidden Risk in Active Directory) and from privileged access drift (rights creeping back in after a cleanup — see Privileged Access Drift Active Directory). Those are about accounts that shouldn't have access anymore, or access that crept back. This is about accounts that are correctly privileged today, sitting without the attribute-level protections Active Directory already ships to contain them.
Detection
Query the directory directly for each gap — none of it requires third-party tooling.
# Privileged accounts NOT in Protected Users
$protected = (Get-ADGroupMember "Protected Users" -Recursive).SamAccountName
Get-ADGroupMember "Domain Admins" -Recursive |
Where-Object { $_.SamAccountName -notin $protected } |
Select-Object SamAccountName
# Privileged accounts missing the "sensitive, cannot be delegated" flag (bit 0x100000)
Get-ADGroupMember "Domain Admins" -Recursive |
Get-ADUser -Properties userAccountControl |
Where-Object { -not ($_.userAccountControl -band 1048576) } |
Select-Object SamAccountName
# Accounts still trusted for unconstrained/constrained delegation
Get-ADUser -Filter 'TrustedForDelegation -eq $true -or msDS-AllowedToDelegateTo -like "*"' `
-Properties TrustedForDelegation, msDS-AllowedToDelegateTo
# Service accounts (SPN set) inside privileged groups
Get-ADGroupMember "Domain Admins","Enterprise Admins" -Recursive |
Get-ADUser -Properties ServicePrincipalNames |
Where-Object { $_.ServicePrincipalNames.Count -gt 0 }
# Any account carrying SID History
Get-ADUser -Filter * -Properties SIDHistory |
Where-Object { $_.SIDHistory.Count -gt 0 } |
Select-Object SamAccountName, SIDHistory
| Indicator | Event ID | Source | Description |
|---|---|---|---|
| Group membership change | 4728 / 4732 / 4756 | Security log (DC) | Account added to Domain Admins / Administrators / Enterprise Admins — baseline and alert on any addition |
| userAccountControl change | 4738 | Security log (DC) | User account changed — includes loss of the "sensitive, cannot be delegated" flag or a delegation flag flip |
| Computer account change | 4742 | Security log (DC) | Same as 4738, for computer accounts (relevant for RBCD via msDS-AllowedToActOnBehalfOfOtherIdentity) |
| Directory object attribute write | 5136 | Security log (DC, requires DS Access auditing) | Fires on the specific attribute modified — filter for sIDHistory to catch SID-History injection directly |
| SID History addition | 4738 (attribute-level) | Security log (DC) | Correlate with recent DsAddSidHistory API calls or tooling such as Mimikatz sid::patch / DSInternals |
For a broader map of which event IDs matter across the rest of your AD estate, see Active Directory Monitoring: Security Event IDs That Matter.
💡 Tip: Baseline your Tier 0 group membership and Protected Users membership on a schedule (weekly is reasonable for most environments) and diff it. Attribute-level gaps like a missing sensitive flag or stray SID History don't trigger a login alert — they only show up if you're actively querying for them.
Remediation
- Populate Protected Users with human Tier 0 accounts only. Test in a pilot group first — Protected Users breaks NTLM-dependent apps, cached/offline logon, and any workflow relying on Kerberos ticket renewal beyond 4 hours. Never add service or computer accounts.
- Set the sensitive flag on every privileged human account:
Do this even for accounts already in Protected Users — Protected Users' delegation block is enforced at authentication, but an explicit sensitive flag is defense in depth and matters immediately for any account not yet fully migrated into the group.
Get-ADUser -Identity "jdoe" | Set-ADAccountControl -AccountNotDelegated:$true - Remove delegation trust from Tier 0 accounts. Clear
TrustedForDelegationandmsDS-AllowedToDelegateToon any privileged account; privileged accounts should never be delegation targets. See our Kerberos Delegation Attacks guide for how to audit delegation configuration domain-wide before you start removing it. - Get service accounts out of privileged groups. Replace Domain Admin membership with a Group Managed Service Account (gMSA) plus narrowly delegated permissions on the specific OU or resource the service actually needs. If the service genuinely needs domain-wide rights, that's a signal to redesign the service, not to leave a Kerberoastable account with full domain privilege.
- Audit and clear stale SID History. Run the detection query above; any
sIDHistoryvalue not tied to a documented, still-relevant domain migration should be investigated and removed withSet-ADUser -Clear sIDHistoryafter confirming no legitimate access depends on it. For cross-forest and external trusts, enable SID filtering (quarantine) so SIDs injected on the other side of the trust are stripped before they reach your domain — see Active Directory Trust Attacks: From Child Domain to Forest Root for how SID filtering gaps get exploited across trusts.
How EtcSec Detects This
EtcSec's Active Directory audit checks all four gaps on every scan: NOT_IN_PROTECTED_USERS flags privileged accounts missing from the Protected Users group, SENSITIVE_DELEGATION catches privileged accounts without the "cannot be delegated" flag, SERVICE_ACCOUNT_PRIVILEGED finds SPN-bearing accounts inside Domain Admins/Enterprise Admins, and SID_HISTORY surfaces any account carrying a non-empty sIDHistory for review.
ℹ️ Note: EtcSec automatically checks for this vulnerability during every AD/Azure audit. Run a free audit to verify your environment.
Explore the identity security pages that support this topic

