AD-INF-003: Domain functional level below Windows Server 2016¶
low Infrastructure Reads: LDAP
The domain functional level is below Windows Server 2016, which leaves out security features that need it and usually means old domain controllers remain.
Also known as: functional-level
Why it matters¶
The functional level decides which features the domain controllers can use. Below Windows Server 2012 R2 the DC-side restrictions for members of Protected Users (no NTLM, no DES or RC4 in Kerberos pre-authentication, no delegation, four-hour TGTs) do not apply, which weakens AD-PRIV-010. Below Windows Server 2016 the DCs cannot roll the NTLM secrets of accounts that require smart-card logon, so a stolen hash of such an account stays valid indefinitely; the 2016 forest level is also what time-bound group membership (Privileged Access Management) needs.
A low level usually exists because an old domain controller is still around, and an old DC carries the unpatched vulnerabilities of its version (AD-INF-001).
How ad-doctor detects it¶
ad-doctor reads msDS-Behavior-Version on the domain object and reports the domain when
the value is below 7 (Windows Server 2016). The detail names the level in words, for
example 2012 R2 for 6. Windows Server 2019 and 2022 have no level of their own; 2016
(7) is the highest level they support, and 10 is Windows Server 2025.
The finding has one object, the domain name, for example corp.example. The forest
functional level is not checked separately.
Attributes and probes read
msDS-Behavior-Version
Severity¶
Always low: a low functional level is not exploitable by itself, but it holds back protections and points at old domain controllers.
False positives and limits¶
None expected. If a DC on an old version must stay for a while, accept the finding with a date by which it will be retired (accepted risks).
Fix¶
-
Find what holds the level down: every DC must run at least the target version.
-
Replace old DCs: promote DCs on a supported version, move FSMO roles, then demote the old ones. Check that applications relying on old behaviour (for example DES) are gone.
-
Raise the domain level, then the forest level. The change replicates to every DC and cannot easily be undone, so dry-run it first:
Verify¶
To accept the risk instead, add an entry to the file passed with --accept (see accepted risks):
[[accept]]
check = "AD-INF-003"
objects = ["..."] # optional; without it the whole check is accepted
reason = "..."
expires = 2027-03-31
Related checks¶
References¶
Microsoft and vendors
Available since 0.1.0.