Broad group has a path to Tier Zero

A group that holds nearly every account, such as Domain Users, has a route to the accounts and servers that control the domain.

Category
Attack Path
Severity
From exposure, usually Critical.
Typical owner
AD / identity team
Data needed
Any collection: SharpHound, RustHound-CE or Pathwarden's built-in collector*. Paths that pass through local administrator rights or logon sessions only appear when sessions and local groups were collected (SharpHound, or the built-in collector* with --user --scope all).
MITRE ATT&CKT1098
On this page

In plain language

Tier Zero is the small set of accounts and servers that control everything else in the domain. When a group like Domain Users or Everyone can reach it, every account in the company has a path to full control, so one phished employee is enough.

This is usually an accident: a permission granted "to everyone" years ago to make something work, or a group nested where it shouldn't be. It is also one of the first things an attacker looks for after getting in. It is among the most valuable findings to fix, and often among the easiest.

What Pathwarden flags

A group that contains practically every account (Domain Users, Domain Computers, Authenticated Users, Everyone, or the builtin Users group) can reach a Tier Zero object such as Domain Admins, a domain controller or the domain itself. Because every account is a member, any single compromised user or workstation is enough to take over the domain.

How attackers use it

After phishing one user, an attacker runs BloodHound and looks for this: a right or nesting granted to a broad group that leads to domain control. No privilege escalation exploit is needed; they use the permission that was granted (for example GenericAll on a privileged group, or Domain Users nested in a local Administrators group on a server where admins log on). Typical follow-ups are account manipulation (T1098) and credential theft from a privileged session.

Find it with Pathwarden

Data needed: Any collection: SharpHound, RustHound-CE or Pathwarden's built-in collector*. Paths that pass through local administrator rights or logon sessions only appear when sessions and local groups were collected (SharpHound, or the built-in collector* with --user --scope all).

In the web UI or the HTML report, open the Findings tab and expand PW-001: each finding shows who can use it (its exposure), the attack path drawn out, the affected objects, and the fix. The remediation path tells you whether a single plan step closes it. On the command line:

Shell
# every finding of this rule, with its path and fix
pathwarden findings -i .\collect --rule PW-001
# the step-by-step guide on this page, offline
pathwarden guide PW-001
# after the fix: collect again, then check it is gone
pathwarden retest -i .\collect-after --rule PW-001

Exit codes make retest easy to script: 0 Fixed, 1 Still open, 3 Can't tell. See findings lifecycle and retest.

Before you change anything

  • Read the attack path in the finding: the fix is usually the first step that is not plain membership (the permission or nesting granted to the broad group).
  • Find out why it was granted. Search change tickets, and check who uses it: for a group nesting, Get-ADGroup <Group> -Properties whenChanged, info, description.
  • For ACL grants, enable auditing of the target object (Directory Service Changes, event 5136) for a short period if you are unsure whether anything relies on it.
  • The report's Remediation path tab lists the smallest set of changes that closes every path, which often fixes this finding together with others.

How to fix it

  1. Identify the first non-membership step of the path in the finding (for example DOMAIN USERS -[GenericAll]-> HELPDESK).
  2. For an ACL: open Active Directory Users and Computers, enable View > Advanced Features, open the target object's Properties > Security > Advanced, and remove every write entry of the broad group the finding names (the path stays open while one is left). Keep its read entries. If an entry is inherited, remove it on the parent container shown in the finding, then check inheritance on the objects below it. On a GPO, use GPMC > the GPO > Delegation > Advanced instead: Authenticated Users and Domain Computers need Read (and Apply group policy where Security Filtering uses it) for the GPO to apply. For the GPO's SYSVOL folder, see PW-027.
  3. For a nesting (for example Domain Users in a privileged group): open the privileged group's Properties > Members, select the broad group, Remove.
  4. For local group membership on a server (AdminTo/CanRDP): remove the broad group from the local group, or from the GPO (Restricted Groups / Group Policy Preferences) that adds it.

Option B: Replace with a dedicated group for each tier

  1. Create a group for the people who actually need the access.
  2. Grant that group the right, then remove the broad group as in Option A.

PowerShell

PowerShell
Import-Module ActiveDirectory

# Nesting: remove a broad group from a privileged group
Remove-ADGroupMember -Identity "<PrivilegedGroup>" -Members "Domain Users" -Confirm:$false

# ACL: list ACEs granted to a broad group on an object
$dn  = (Get-ADObject -Identity "<TargetDN>").DistinguishedName
$acl = Get-Acl -Path "AD:\$dn"
$acl.Access | Where-Object { $_.IdentityReference -match "Domain Users|Authenticated Users|Everyone" }

# ACL: remove the explicit (non-inherited) ACEs that grant the rights the finding
# names, and save. Add any other right it names to the pattern; leave read entries
# and default extended rights (Change Password, Apply Group Policy) in place
$acl.Access | Where-Object {
    $_.IdentityReference -match "Domain Users|Authenticated Users|Everyone" -and -not $_.IsInherited -and
    $_.ActiveDirectoryRights -match "GenericAll|GenericWrite|WriteDacl|WriteOwner"
} | ForEach-Object { [void]$acl.RemoveAccessRule($_) }
Set-Acl -Path "AD:\$dn" -AclObject $acl

Verify the fix

PowerShell
(Get-Acl -Path "AD:\<TargetDN>").Access |
    Where-Object { $_.IdentityReference -match "Domain Users|Authenticated Users|Everyone" }
Get-ADGroupMember "<PrivilegedGroup>" | Select-Object Name

Both should return nothing for the broad group. Collect again (or use Retest on the finding) and confirm the finding ID is gone.

Roll back

Re-add the removed ACE or membership (Get-Acl output saved before the change can be re-applied with Set-Acl). Save (Get-Acl "AD:\<TargetDN>").Sddl to a file before editing so the original security descriptor can be restored.

References

  1. Microsoft: Securing privileged access reference materiallearn.microsoft.com
  2. SpecterOps: BloodHound documentationbloodhound.specterops.io
  3. SpecterOps BloodHound docs: GenericAllbloodhound.specterops.io
  4. SpecterOps BloodHound docs: MemberOfbloodhound.specterops.io
  5. Microsoft: Best practices for securing Active Directorylearn.microsoft.com
  6. MITRE ATT&CK T1098: Account Manipulationattack.mitre.org

Very new and undergoing testing. These features haven't received a lot of testing yet. Try them out and let us know what's working.

↑↓ to moveEnter to openEsc to close