Domain Controller Hardening¶
A domain controller holds every password hash in the domain and issues every ticket. Anyone who is an administrator on the DC is an administrator everywhere. These are the settings the benchmark reserves for the Domain Controller profile; set them in gpmc.msc → Domain Controllers OU → Default Domain Controllers Policy, or in secpol.msc on the DC when the domain policy doesn't set them.
User rights on a DC¶
The rights below differ from the standalone values on the User Rights Assignment page. Everything not listed keeps its standalone value. ENTERPRISE DOMAIN CONTROLLERS is the group of every DC; DCs need to reach each other for replication.
| CIS | Right | DC value | Why |
|---|---|---|---|
| 2.2.2 | Access this computer from the network | Administrators, Authenticated Users, ENTERPRISE DOMAIN CONTROLLERS | Members authenticate against the DC over the network, and DCs replicate with each other |
| 2.2.5 | Add workstations to domain | Administrators | By default any authenticated user can join ten machines to the domain. A machine an attacker controls in the domain is a foothold. |
| 2.2.7 | Allow log on locally | Administrators, ENTERPRISE DOMAIN CONTROLLERS | Only DC administrators sit at the DC console |
| 2.2.9 | Allow log on through Remote Desktop Services | Administrators | No Remote Desktop Users group on a DC |
| 2.2.17 | Create symbolic links | Administrators | No Hyper-V entry on a DC |
| 2.2.20 | Deny access to this computer from the network | Guests (STIG WN22-DC-000370) | On a DC the standalone "Local account" entry isn't used; there are no local accounts |
| 2.2.25 | Deny log on through Remote Desktop Services | Guests (STIG WN22-DC-000410) | Same |
| Deny log on as a batch job, Deny log on locally | Guests (STIG WN22-DC-000380, 000400) | Same | |
| Deny log on as a service | Blank (STIG WN22-DC-000390) | Denying Domain Admins here breaks services the DC itself runs | |
| 2.2.27 | Enable computer and user accounts to be trusted for delegation | Administrators | Delegation lets a service impersonate users; on a DC only administrators configure it (members: No One) |
| 2.2.31 | Impersonate a client after authentication | Administrators, LOCAL SERVICE, NETWORK SERVICE, SERVICE | |
| 2.2.36 | Log on as a batch job | Administrators (Level 2) | Scheduled tasks on the DC run as administrators only |
| 2.2.37 | Manage auditing and security log | Administrators | Whoever holds this can clear the Security log. On a DC, Exchange servers sometimes appear here; the README says whether that's legitimate. |
| 2.2.47 | Synchronize directory service data | No One | Lets a process read the whole directory, hashes included. Nothing needs it. |
The Windows 11 STIG's "deny Domain Admins everywhere" rule from the user rights page is for workstations and members. Don't apply it to a DC: Domain Admins are the DC's administrators.
Security options for a DC¶
secpol.msc → Local Policies → Security Options → the Domain controller: entries (or the same path in the Default Domain Controllers Policy).
| CIS | Setting | Value | Why |
|---|---|---|---|
| 2.3.5.1 | Domain controller: Allow server operators to schedule tasks | Disabled | A scheduled task on a DC runs as SYSTEM. Server Operators aren't Domain Admins and shouldn't get a path to become one. |
| 2.3.5.2 | Domain controller: Allow vulnerable Netlogon secure channel connections | Not Configured | Configuring it creates exceptions to the Zerologon (CVE-2020-1472) fix. An image that set it Enabled reopened the hole. |
| 2.3.5.3 | Domain controller: LDAP server channel binding token requirements | Always | Binds the LDAP session to its TLS channel so a relayed LDAP login fails |
| 2.3.5.4 | Domain controller: LDAP server signing requirements | Require signing (STIG WN22-DC-000320) | Unsigned LDAP can be modified in transit; an attacker on the network can rewrite a query that adds them to a group |
| 2.3.5.5 | Domain controller: Refuse machine account password changes | Disabled (STIG WN22-DC-000330) | Members rotate their machine passwords every 30 days; refusing the change leaves them on old passwords forever |
| 2.3.11.12 | Network security: Restrict NTLM: Audit NTLM authentication in this domain | Enable all | Logs every NTLM login the DC handles, so you can see what hasn't moved to Kerberos |
reg add "HKLM\SYSTEM\CurrentControlSet\Services\NTDS\Parameters" /v LDAPServerIntegrity /t REG_DWORD /d 2 /f
reg add "HKLM\SYSTEM\CurrentControlSet\Services\NTDS\Parameters" /v LdapEnforceChannelBinding /t REG_DWORD /d 2 /f
reg add "HKLM\SYSTEM\CurrentControlSet\Services\Netlogon\Parameters" /v RefusePasswordChange /t REG_DWORD /d 0 /f
reg delete "HKLM\SYSTEM\CurrentControlSet\Services\Netlogon\Parameters" /v VulnerableChannelAllowList /f
reg add "HKLM\SYSTEM\CurrentControlSet\Services\Netlogon\Parameters" /v FullSecureChannelProtection /t REG_DWORD /d 1 /f
reg add "HKLM\SYSTEM\CurrentControlSet\Services\Netlogon\Parameters" /v AuditNTLMInDomain /t REG_DWORD /d 7 /f
FullSecureChannelProtection = 1 is the enforcement half of the Zerologon fix; keep it.
Administrative Templates for a DC¶
| CIS | Setting | Path (Computer Configuration → Administrative Templates) | Value | Why |
|---|---|---|---|---|
| 18.9.27.1 | Allow Custom SSPs and APs to be loaded into LSASS | System → Local Security Authority | Disabled | A custom security package loaded into LSASS sees every password as it's typed. This is how the mimikatz "SSP" attack works. |
| 18.9.41.1 | Configure validation of ROCA-vulnerable WHfB keys during authentication | System → Security Account Manager | Enabled: Block | Rejects Windows Hello keys generated by a known-weak TPM firmware |
| 18.9.5.6 | Turn On Virtualization Based Security: Credential Guard Configuration | System → Device Guard | Disabled (Next Generation Windows Security profile) | Credential Guard on a DC breaks the directory's own authentication; the other VBS settings stay on |
reg add "HKLM\SOFTWARE\Policies\Microsoft\Windows\System" /v AllowCustomSSPsAPs /t REG_DWORD /d 0 /f
Services on a DC¶
Print Spooler is Level 1 disable on a DC (5.1), not Level 2 as elsewhere: the spooler runs as SYSTEM on the machine that holds every credential, and PrintNightmare against a DC is a full-domain compromise.
Stop-Service Spooler; Set-Service Spooler -StartupType Disabled
A DC should run only the DC role and what the README adds (STIG WN22-DC-000130). DNS is normal on a DC. A web server, a file share for users, or a database on the DC puts that application's bugs on the machine that can least afford them; if the README requires a role the DC shouldn't hold, harden it as the Server Roles pages describe, and don't move it.
LDAP idle timeout¶
The STIG (WN22-DC-000160) wants idle LDAP connections closed after 5 minutes, which limits how long a hijacked session stays open. Default is 15 minutes.
ntdsutil
LDAP policies
connections
connect to server localhost
q
Set MaxConnIdleTime to 300
Commit Changes
Show Values
q
q
Verify¶
reg query "HKLM\SYSTEM\CurrentControlSet\Services\NTDS\Parameters" /v LDAPServerIntegrity
reg query "HKLM\SYSTEM\CurrentControlSet\Services\Netlogon\Parameters"
Get-Service Spooler | Select Status, StartType
secedit /export /cfg C:\dc-rights.inf; findstr /i "SeSyncAgentPrivilege SeMachineAccountPrivilege SeInteractiveLogonRight SeRemoteInteractiveLogonRight SeEnableDelegationPrivilege" C:\dc-rights.inf
SeSyncAgentPrivilege shouldn't appear at all (No One). SeMachineAccountPrivilege should be *S-1-5-32-544 (Administrators) only.
Example¶
findstr SeMachineAccountPrivilege returns *S-1-5-11 (Authenticated Users): anyone in the domain can add computers. Set it to Administrators. LDAPServerIntegrity is 1 (negotiate). Set it to 2. Get-ADGroupMember "Server Operators" shows bob, and the DC allows server operators to schedule tasks; the README doesn't make bob an administrator, so remove him and disable the setting.