Active Directory Monitoring Blind Spots: Display Specifiers, RODC, and Two More
Active Directory monitoring blind spots — display specifiers, RODC credential caching, Default Domain Policy tampering, and PAM shadow principals — rarely show up on a standard security review, even though all four are documented Microsoft mechanisms that can hand an attacker persistence or privileged access while the usual dashboards (Domain Admins membership, DCSync rights, ACL changes on Tier 0 objects) stay green. They're blind spots because nobody points a SACL or a query at them, not because they're hidden.
This piece covers each in turn: what the object or mechanism actually is, how it gets abused or drifts, what to watch to catch it, and how to fix it.
Display Specifiers: A UI Extension Point Turned Persistence Backdoor
The Mechanism
Display specifiers are objects of class displaySpecifier, stored in locale-specific containers under CN=DisplaySpecifiers,CN=Configuration,DC=<forest-root> — for example CN=user-Display,CN=409,CN=DisplaySpecifiers,CN=Configuration. Because they live in the Configuration naming context, they replicate to every domain controller in the forest. Their documented purpose, per Microsoft's Win32 AD programming reference, is entirely legitimate: they store the data behind property sheets, context menus, icons, and creation wizards in MMC-based tools like Active Directory Users and Computers (ADUC).
The attributes that make this interesting from a security standpoint are adminContextMenu and adminPropertyPages (administrative snap-ins) and their non-admin counterparts contextMenu/shellContextMenu — all documented in Microsoft's [MS-ADTS] protocol spec and the Display-Specifier schema class reference. Each can register a COM object or an application to run when an admin interacts with an object through ADUC. Security researchers at Semperis and SDM Software have documented the abuse case directly: an attacker with write access to a display specifier can add a bogus context-menu entry — one that looks like a normal action (say, a password reset option) — that actually launches a script when a helpdesk admin right-clicks a user object.
⚠️ Warning: by default, only Domain Admins and Enterprise Admins can write to the DisplaySpecifiers container, so this is a post-compromise persistence technique, not an initial-access path. That's exactly what makes it dangerous — it survives credential rotation and even a Tier 0 admin account rebuild, because the backdoor lives in a UI extension point, not in a privileged account.
Detection
Directory object modifications generate Windows Security Event ID 5136 ("A directory service object was modified"), but only if two conditions are both met: the DC has the "Audit Directory Service Changes" advanced audit subcategory enabled, and the target object carries a SACL for the relevant attributes. Neither is on by default for the DisplaySpecifiers container — which is precisely why this blind spot exists. Once auditing is in place, watch 5136 events where the object class is displaySpecifier and the changed attribute is adminContextMenu, adminPropertyPages, contextMenu, or shellContextMenu. See Active Directory Monitoring: Security Event IDs That Matter for the broader audit-policy baseline these checks assume.
# Enumerate all display specifier objects and their menu/property-page attributes
Get-ADObject -SearchBase "CN=DisplaySpecifiers,CN=Configuration,$((Get-ADRootDSE).configurationNamingContext)" `
-Filter "objectClass -eq 'displaySpecifier'" `
-Properties adminContextMenu, adminPropertyPages, contextMenu, shellContextMenu |
Where-Object { $_.adminContextMenu -or $_.adminPropertyPages -or $_.contextMenu -or $_.shellContextMenu } |
Select-Object Name, adminContextMenu, adminPropertyPages, contextMenu, shellContextMenu
A clean baseline for this query is an empty result set on most domains — any hit deserves manual review of the referenced COM CLSID or application path.
Default Domain Policy Tampering: Silent Changes to the Domain's Security Baseline
The Mechanism
The Default Domain Policy carries a well-known, forest-independent GUID — {31B2F340-016D-11D2-945F-00C04FB984F9} — and enforces the domain-wide account, password, Kerberos, and lockout policy baseline unless overridden by a more specific GPO. Because that GUID is hardcoded and predictable, and because the GPO is old enough that most teams stopped reviewing it after initial hardening, changes to it tend to go unnoticed. MITRE ATT&CK tracks GPO tampering as sub-technique T1484.001 (Domain or Tenant Policy Modification: Group Policy Modification) — adversaries alter GPOs to weaken account lockout thresholds, disable password complexity, or push a scheduled task/logon script to every computer that applies the policy.
Detection
Two separate event IDs cover different layers of a GPO change, and conflating them is a common mistake:
- Event ID 5136 ("A directory service object was modified") fires on the
groupPolicyContainerAD object itself when the "Audit Directory Service Changes" subcategory and an object SACL are both in place. Security content from Splunk's detection research and MITRE's own detection guidance both call out watching thegPCFileSysPath,gPCMachineExtensionNames, andversionNumberattributes specifically — a version bump with no corresponding SYSVOL change request is itself a signal worth flagging. - Event ID 4739 ("Domain Policy was changed") fires when the effective account policy — lockout threshold, password policy, Kerberos policy — actually changes, whether that change came through Group Policy or Local Security Policy. It's the higher-signal event for "did the security baseline itself move," but it won't tell you which GPO or admin made the edit — pair it with 5136 for attribution.
# Splunk-style detection sketch: Default Domain Policy object modification
index=wineventlog EventCode=5136 ObjectDN="*CN=Policies,CN=System,DC=*"
| search ObjectDN="*{31B2F340-016D-11D2-945F-00C04FB984F9}*"
| table _time, SubjectUserName, AttributeLDAPDisplayName, AttributeValue, OperationType
💡 Tip: allow 15–30 minutes for a policy change to replicate across domain controllers before treating an absence of the expected effect as a false negative — Group Policy replication and refresh cycles aren't instantaneous. Related drift shows up in GPO misconfigurations and in overly broad dangerous user rights pushed through the same delivery mechanism.
PAM Shadow Principals: Ephemeral Admin Access That Standard Queries Miss
The Mechanism
Windows Server's Privileged Access Management (PAM) feature, built on Microsoft Identity Manager, grants time-bound privileged access without ever adding an account to a standing group like Domain Admins. Microsoft's own PAM documentation describes the mechanism: a shadow principal — an object of class msDS-ShadowPrincipal, created only inside the default CN=Shadow Principal Configuration container under CN=Services in the Configuration NC of a bastion forest — carries an msDS-ShadowPrincipalSid attribute mapping it to a privileged group SID in the production forest (e.g., Domain Admins). Membership in that shadow principal is granted with a time-to-live (TTL) using the AD Expiring Links feature (Windows Server 2016+): the KDC caps any Kerberos ticket it issues to the remaining TTL on the link, so access genuinely expires rather than relying on someone remembering to remove it.
The blind spot: expiring group links are stored as ordinary member attribute values with a TTL flag, but that TTL is only visible to a query that explicitly passes the LDAP_SERVER_LINK_TTL extended control (OID 1.2.840.113556.1.4.2309), as documented by DSInternals' research into how Expiring Links actually work. A routine "who's in this group" query that doesn't pass that control sees a normal-looking membership — no expiry, no obvious time-bound flag — which means an admin scanning shadow principal groups with generic AD auditing tooling can miss that the access is ephemeral by design, or miss short-lived membership additions entirely if the scan interval is longer than the TTL.
Detection
Shadow principal groups are still security-group-class objects, so membership adds generate the same standard AD group-membership events as any other group, scoped by group type: 4728 (member added to a global security group), 4732 (domain local), 4756 (universal). Filter these events specifically for objects inside CN=Shadow Principal Configuration,CN=Services,CN=<config-NC> to isolate PAM activations from routine group administration.
# List current shadow principals and their mapped production-forest SID
Get-ADObject -SearchBase "CN=Shadow Principal Configuration,CN=Services,$((Get-ADRootDSE).configurationNamingContext)" `
-Filter "objectClass -eq 'msDS-ShadowPrincipal'" `
-Properties 'msDS-ShadowPrincipalSid', member |
Select-Object Name, 'msDS-ShadowPrincipalSid', @{N='MemberCount';E={$_.member.Count}}
ℹ️ Note: if your forest doesn't run a PAM bastion-forest deployment, EPHEMERAL_ADMINS_PAM should simply return clean — but it's worth confirming that explicitly rather than assuming, since the container can exist unused after an abandoned pilot.
RODC Credential Caching, In Brief
Read-Only Domain Controllers (RODCs) are deployed specifically for low-trust sites — branch offices, physically exposed locations — on the assumption that if one is compromised, the blast radius is limited to whichever account passwords it was allowed to cache. That boundary is enforced by two group memberships: the Allowed RODC Password Replication Group (empty by default — an RODC caches nothing until explicitly permitted) and the Denied RODC Password Replication Group, corresponding to the msDS-RevealOnDemandGroup and msDS-NeverRevealGroup attributes documented by Microsoft. What actually got cached is visible via msDS-RevealedList; who authenticated through the RODC is in msDS-AuthenticatedToAccountlist.
This is the one blind spot in this piece where the fix is a policy question, not a monitoring gap most teams haven't heard of — EtcSec has already covered the full detection and remediation path for RODC privileged caching, including the exact Password Replication Policy misconfigurations that let a Tier 0 credential land somewhere it should never be replicated. See RODC Privileged Credential Caching: Read-Only Domain Controller Holds Domain Admin Hashes for the deep dive; the summary here is deliberately brief to avoid duplicating it.
Detection: What to Actually Watch For
| Blind spot | Indicator | Event ID / Attribute | Source |
|---|---|---|---|
| Display specifiers | Write to adminContextMenu, adminPropertyPages, contextMenu, shellContextMenu on a displaySpecifier object | 5136 (requires SACL + Directory Service Changes auditing) | Domain controller Security log |
| Default Domain Policy | versionNumber, gPCFileSysPath, gPCMachineExtensionNames change on GUID {31B2F340-016D-11D2-945F-00C04FB984F9} | 5136 | Domain controller Security log |
| Default Domain Policy | Effective account/lockout/Kerberos policy change | 4739 | Domain controller Security log |
| PAM shadow principals | Member added to a group under CN=Shadow Principal Configuration | 4728 / 4732 / 4756 (by group scope) | Bastion forest Security log |
| RODC credential caching | Principal added to msDS-RevealOnDemandGroup or appears in msDS-RevealedList | See dedicated RODC article | RODC Security log / repadmin |
None of these require a new logging pipeline — they need SACLs placed on objects that ship without them, and someone querying attributes that standard AD health-check scripts don't touch.
Remediation
💡 Quick Win: enable the "Audit Directory Service Changes" advanced audit subcategory on all domain controllers if it isn't already — it's the single control that turns three of these four blind spots from silent to logged.
Step-by-Step
- Display specifiers. Place a SACL for "Write all properties" (or, more narrowly, the specific menu/property-page attributes) on
CN=DisplaySpecifiers,CN=Configuration,DC=<forest-root>and its children. Baseline the currentadminContextMenu/adminPropertyPagesvalues now, since a compromised backdoor could already be present. - Default Domain Policy. Apply a SACL to the Default Domain Policy's
groupPolicyContainerobject and to its SYSVOL folder (\\<domain>\SYSVOL\<domain>\Policies\{31B2F340-016D-11D2-945F-00C04FB984F9}). Alert on any 5136/4739 pair that doesn't correspond to a tracked change ticket. - PAM shadow principals. If PAM/MIM isn't intentionally deployed, confirm the
CN=Shadow Principal Configurationcontainer is empty and stays that way. If it is deployed, review shadow principal membership on a cadence that accounts for TTLs shorter than your review interval — a link that expired between two weekly scans never shows up in either one unless you're diffing 4728/4732/4756 events, not just point-in-time membership snapshots. - RODC credential caching. Confirm the Allowed RODC Password Replication Group contains no Tier 0 principals, directly or through nested group membership — see the dedicated article linked above for the full remediation walkthrough, including the specific replication policy checks.
- Feed all five event IDs above (5136, 4739, 4728, 4732, 4756) into whatever SIEM already ingests your Active Directory audit policy baseline — this is an extension of existing Account Management and Policy Change auditing, not a new logging category, and it pairs naturally with existing GPO monitoring and privileged access review processes.
How EtcSec Detects This
EtcSec's Advanced and Computers detectors flag all four of these blind spots automatically during every AD audit: DISPLAY_SPECIFIER_CHANGES catches recent modifications to display specifier objects, DEFAULT_DOMAIN_POLICY_CHANGED flags edits to the domain's baseline security policy, EPHEMERAL_ADMINS_PAM surfaces PAM shadow principal activity (including short-TTL memberships that a manual snapshot would miss), and RODC_PRIVILEGED_CACHING — rated Critical — catches Tier 0 credentials replicated to an RODC.
ℹ️ Note: EtcSec automatically checks for all four of these during every AD audit. Run a free audit to see whether any of them are already active in your environment.
Explore the identity security pages that support this topic
