Skip to content

AD-INF-004: Unsafe dsHeuristics settings

low medium high   Infrastructure   MITRE ATT&CK T1087.002, T1098   Reads: LDAP

The forest-wide dSHeuristics value weakens the directory: anonymous LDAP or NSPI, operators outside AdminSDHolder, uniqueness or encryption checks off, or CVE-2021-42291 checks disabled.

Also known as: dsheuristics

Why it matters

dSHeuristics on CN=Directory Service,CN=Windows NT,CN=Services in the configuration partition is a string of single-character switches that change directory behaviour for the whole forest. Positions count from 1, as MS-ADTS numbers them. These weaken security:

  • 3rd character 1 (fDoListObject). Turns on List Object mode, so LIST_OBJECT rights are enforced. It is not a weakness by itself, and some forests use it to hide objects, but an account denied that right sees nothing of the object. The scan then can miss objects with no error, so its results may be incomplete.

  • 7th character 2 (fLDAPBlockAnonOps off). Anonymous LDAP clients may run operations beyond the rootDSE, limited only by ACLs. Together with Anonymous Logon or Everyone in Pre-Windows 2000 Compatible Access (AD-PRIV-005), anyone on the network can enumerate users, groups and computers without an account, which feeds password spraying and target selection.

  • 8th character not 0 (fAllowAnonNSPI). Anonymous clients may call the NSPI RPC bind method, the address book interface, instead of authenticated clients only.
  • 16th character (dwAdminSDExMask) not 0. The hex digit removes Account, Server, Print and/or Backup Operators from AdminSDHolder protection. Their members then keep whatever ACL their own objects carry, so a helpdesk ACE inherited from an OU can be used to reset the password of an operator and, through the operator group's rights on DCs, climb to domain admin (AD-PRIV-008).
  • 21st character (DoNotVerifyUPNAndOrSPNUniqueness). A bitwise value: bit 0 stops the uniqueness check on userPrincipalName, bit 1 on servicePrincipalName, bit 2 the SPN alias check. Duplicates are then possible, and Kerberos can resolve a name to the wrong account.
  • 28th character 2 (AttributeAuthorizationOnLDAPAdd) and 29th character 2 (BlockOwnerImplicitRights). KB5008383 heads these Additional AuthZ verifications for LDAP Add operations and Temporary removal of Implicit Owner for LDAP Modify operations. They guard computer objects against CVE-2021-42291: 0 audits, 1 enforces, 2 turns both off. Microsoft marks 2 as not recommended.
  • 31st character (DisableConfidentialAttributeEncryptionRequirements). A bitwise value: bit 0 allows reading confidential attributes over an unencrypted connection, bit 1 writing them on modify, bit 2 on add. They then cross the network in clear text.

How ad-doctor detects it

ad-doctor reads dSHeuristics from the configuration partition and checks characters 3, 7, 8, 16, 21, 28, 29 and 31. A character past the end of the string, or a value that is not set (the default), takes its default and is not reported. That includes 28 and 29: unset means audit mode, the state of most forests, and only an explicit 2 is reported, not a missing 1. When the object cannot be read at all, the report has a note instead of a clean result.

The object is the dSHeuristics string itself, for example 0000002 (anonymous operations allowed); the detail names each character found.

Attributes and probes read
  • dSHeuristics

Severity

The highest grade among the characters set:

  • High: anonymous LDAP operations (7th character 2) or anonymous NSPI (8th not 0).
  • Medium: AdminSDHolder exclusion (16th not 0), uniqueness checks off (21st), CVE-2021-42291 checks disabled (28th or 29th 2), confidential attributes without encryption (31st).
  • Low: List Object mode (3rd 1), which is mostly about what this scan can see, and values that cannot be judged (28th or 29th 3, or a 21st or 31st that is not a known bit).

False positives and limits

  • Applications that need anonymous LDAP, such as some old printers or Unix clients. Give them a service account instead; if that is impossible, accept the finding with an owner and an expiry date (accepted risks).
  • A deliberate AdminSDHolder exclusion for an operator group that is kept empty is low risk, but the clean fix is to reset the character and leave the group empty.
  • List Object mode set on purpose, for example to hide tenants from each other. Accept it, and scan with an account that can list everything.

Fix

  1. Read the current value.

    $ds = "CN=Directory Service,CN=Windows NT,CN=Services,$((Get-ADRootDSE).configurationNamingContext)"
    (Get-ADObject $ds -Properties dSHeuristics).dSHeuristics
    
  2. Reset the affected characters to 0, except the 28th and 29th: set those to 1 to enforce KB5008383 once its audit events are clean. If no other character is set on purpose, clear the attribute; otherwise write the string back with only those positions changed (keep the 10th character 1, the 20th 2 and the 30th 3 when the string is that long: they are check characters). Run as an Enterprise Admin:

    Set-ADObject $ds -Clear dSHeuristics -WhatIf
    Set-ADObject $ds -Replace @{dSHeuristics = '0000000'} -WhatIf
    
  3. If the AdminSDHolder exclusion was removed, wait for SDProp to run (every 60 minutes) and check that the operator accounts got the protected ACL.

Verify

ad-doctor scan dc01.corp.example --ldaps -u 'CORP\auditor' --only AD-INF-004

To accept the risk instead, add an entry to the file passed with --accept (see accepted risks):

[[accept]]
check = "AD-INF-004"
objects = ["..."]        # optional; without it the whole check is accepted
reason = "..."
expires = 2027-03-31

References

Microsoft and vendors

Specifications

MITRE ATT&CK

Available since 0.1.0.