Authenticated Users Can Add Domain Computers: zero the quota, delegate the join
By default, any domain user can join up to 10 computers to your AD. It's the opening move of noPac, RBCD and relay chains. Set the quota to zero, tighten the user right, and delegate joins properly.
01 The Big PictureFor leadership · no jargon
Okay, so this one is less a vulnerability and more a default that has been quietly waiting to ruin your day since Windows 2000. Out of the box, Active Directory lets any authenticated user join up to ten computers to the domain. Any user. A friend of mine found this out when an employee casually mentioned he'd joined his personal laptop to the corporate domain; he didn't believe him until he checked. Think of it as the front desk handing every badge holder ten blank machine badges, no questions asked: convenient right up until the person holding the badge shouldn't be enrolling anything.
The catch is that the badge itself is the prize. A freshly joined laptop gains nothing on its own (if anything it loses freedom once your group policies land on it), but the computer account it creates inside the directory is a genuine foothold: it can authenticate to the network, it can be renamed, and it can be wired into delegation tricks. That account is the opening move of attack chains that turned a single phished login into full domain control, most famously the 2021 noPac chain, which Secureworks demonstrated end to end in sixteen seconds. It's why a pentester holding valid credentials checks this setting almost first: it's the cheapest way to convert "we got one login" into "we need to talk about your domain controllers".
The fix is two small changes plus a bit of delegation hygiene: set one directory attribute to zero, tighten one user right, and give the people who legitimately image machines a proper join account. Minutes of work, no downtime, and existing computers won't notice a thing. The only real trade-off is that provisioning workflows that were leaning on the default (imaging, helpdesk joins, some clustering) need to move onto delegated accounts first, or they'll be the ones calling you on Monday.
02 Technical BreakdownFor engineers
Two separate mechanisms conspire here. The first is the user right "Add workstations to domain" (SeMachineAccountPrivilege): on domain controllers the effective default grants it to Authenticated Users, and here's the sneaky part, it isn't set in any GPO out of the box (the Default Domain Controllers Policy shows it as Not Defined). The grant lives in the DCs' local security policy, which means a GPO configured as "Not Defined" changes absolutely nothing. You have to define the setting explicitly to remove the default.
The second mechanism is the ms-DS-MachineAccountQuota attribute on the domain naming context head (DC=corp,DC=example,DC=com), default value 10. It caps how many computer accounts a non-privileged user may create via the join path, and AD tracks usage by stamping the creator's SID into each new computer object's ms-DS-CreatorSID attribute. Domain Admins, and anyone delegated Create Computer Objects on a container, bypass the quota entirely. Can you see where this is going? The two paths are independent: removing the user right doesn't stop someone with a container delegation, and a quota of zero doesn't either. Both need attention, which is exactly the consensus answer every time this comes up on r/sysadmin.
Once the account exists, its creator gets write access to a rather handy set of attributes: the SPNs, the sAMAccountName, and msDS-AllowedToActOnBehalfOfOtherIdentity (the resource-based constrained delegation switch) among them. Validation is strict at creation time and relaxed afterwards, which is the entire trick behind noPac: create a machine account (thank you, quota), rename it to a DC's name minus the $ (CVE-2021-42278), grab a TGT, rename back, and abuse the KDC's helpful retry-with-a-dollar behaviour to get a service ticket as the DC (CVE-2021-42287). Then DCSync, then it's game over. Microsoft patched both CVEs in November 2021 (KB5008102, KB5008380) and CISA lists them as exploited in the wild, but the relay and delegation chains (Wagging the Dog, KrbRelayUp and friends) still happily consume a spare machine account today. Worth being precise here: zeroing the quota is attack-surface reduction, not a patch substitute. An attacker who already controls a machine account doesn't need a new one. Patch the DCs, then close the tap.
03 Affected
Every Active Directory domain from Windows 2000 onwards where the defaults are untouched, including fully patched ones. The October 2022 domain-join hardening (KB5020276, CVE-2022-38042) only governs reusing existing computer accounts during a join, and Microsoft is explicit that it "does not affect new accounts". A 2026-patched domain is just as open here as a 2010 one.
Existing, already-joined computers are completely unaffected by the fix: their secure channel, their policies and their trust relationship carry on as before; only new account creation by non-privileged users stops. Entra ID and Intune enrolment are a separate universe with their own device limits and don't care about the on-prem quota at all. One genuinely awkward case: AWS Managed Microsoft AD tenants can't change the attribute at all, and AWS's delegated join group contains Domain Users, so the default is effectively unfixable there; monitoring and ACL hygiene are your compensating controls.
04 Detection
Before we change anything, let's see what we're dealing with. First, the quota itself:
Get-ADObject ((Get-ADDomain).distinguishedname) -Properties ms-DS-MachineAccountQuota10 is the default. You want 0. (If it comes back blank, set it explicitly rather than assuming: sources disagree on whether an unset attribute means the default applies.)
Next, who holds the user right? The effective value lives on the DCs, so ask one directly:
secedit /export /areas USER_RIGHTS /cfg C:\Temp\user-rights.inf Look for the SeMachineAccountPrivilege line. *S-1-5-11 is Authenticated Users, which is the finding. Don't trust the GPO consoles here: Not Defined in the Default Domain Controllers Policy still means the DC's local default applies.
Now the retrospective hunt: which computers were joined by mere mortals?
Get-ADComputer -Filter 'mS-DS-CreatorSID -like "*"' -Properties mS-DS-CreatorSID |
Select-Object Name, @{N='CreatedBy';E={
(New-Object System.Security.Principal.SecurityIdentifier($($_."mS-DS-CreatorSID"))).
Translate([System.Security.Principal.NTAccount]).Value}}Every hit is a computer a non-admin joined. Blank output isn't an all-clear though: admin-created accounts never get the attribute, so this only ever surfaces user creations.
And going forward, watch event 4741 (computer account created) on your DCs, with an alert when the subject account isn't your imaging or helpdesk group. Two bonus hunts while you're in there: computer accounts whose sAMAccountName doesn't end in $ (Microsoft's own noPac hunt: Get-ADComputer -LDAPFilter "(samAccountName=*)" | Where-Object SamAccountName -NotLike "*$"), and disabled-but-present computer objects, since a user can disable but never delete the accounts it creates. Pentest leftovers have a habit of lingering.
05 Remediation
01 Set the machine account quota to zero
One attribute on the domain head, effective immediately, no reboot, and it touches nothing that already exists. Microsoft documents the mechanism in KB 243327; the set-it-to-zero recommendation itself is practitioner consensus (Microsoft's own 2025 join-permissions doc conspicuously never mentions the attribute, make of that what you will), and Secure Score / Defender for Identity flags the default under "Resolve unsecure domain configurations", which conveniently gives you an external re-check afterwards.
Set-ADDomain -Identity (Get-ADDomain).distinguishedname -Replace @{"ms-DS-MachineAccountQuota"=0} Needs Domain Admin. Or ADSI Edit: Default naming context, domain object properties, Attribute Editor, ms-DS-MachineAccountQuota = 0.
Remember what this does and doesn't do: 0 blocks quota-bound users (everyone except admins and delegated accounts, who were never quota-bound). It is not a patch, and it doesn't remove the user right. That's next.
02 Tighten "Add workstations to domain"
Edit the Default Domain Controllers Policy (or a GPO linked to the Domain Controllers OU): Computer Configuration > Windows Settings > Security Settings > Local Policies > User Rights Assignment > Add workstations to domain. Define it explicitly, for example Administrators plus your dedicated join group, and gpupdate /force the DCs. Microsoft's current guidance goes further and says it doesn't recommend using this right at all; delegate instead, which is the next step.
"Not Defined" is the trap: it leaves the DC-local Authenticated Users grant in place. The setting must be defined to change anything.
One more sweep before you declare victory: check the ACLs on CN=Computers and your OUs for stale delegations to Authenticated Users. An old "write all properties" delegation keeps the door wide open regardless of both settings above (this has bitten real people on r/sysadmin who'd "fixed" the GPO and wondered why joins still worked).
03 Delegate joins to the people who actually need them
Your imaging account (SCCM/MDT task sequences), helpdesk and build teams shouldn't be Domain Admins and shouldn't need the quota. Give a dedicated join account Create Computer Objects on the specific OUs it builds into, or better, use offline domain join (djoin /provision on a provisioning box, djoin /requestODJ on the target), which Microsoft recommends precisely because it needs no AD permissions at join time. If you pre-stage accounts and rejoin later, remember KB5020276: since October 2022 only the account's creator (or a Domain Admin-created account, or an allow-listed owner) may reuse it, so imaging flows that pre-stage under one account and join under another break with error 0xaac.
Two gotchas worth the faff. First, whoever creates a computer object owns it, and ownership is a foothold: the computer class schema grants the creator read rights that leak Legacy LAPS passwords (ms-Mcs-AdmPwd) and allow RBCD writes on every machine that account ever builds. Transfer ownership to Domain Admins after creation, or add deny ACEs on those attributes. Second, run redircmp "OU=Workstations,DC=corp,DC=example,DC=com" so freshly joined machines land in a real OU: the default Computers container can't take group policies, which is where surprises go to live.
06 Verification
Patched and zeroed? Let's prove it rather than assume it.
Get-ADObject ((Get-ADDomain).distinguishedname) -Properties ms-DS-MachineAccountQuotaExpect 0. Secure Score should stop flagging the domain within its next assessment cycle too.
secedit /export /areas USER_RIGHTS /cfg C:\Temp\user-rights.inf SeMachineAccountPrivilege should no longer list *S-1-5-11; only your approved groups.
Now the attacker's-eye view, the exact check a pentester runs against you:
nxc ldap <DC_IP> -u <user> -p <pass> -M maqAny ordinary user's creds will do; that's the point. Expect the module to report 0.
And the full end-to-end test, as a bog-standard user:
New-MachineAccount -MachineAccount "quota-check" -VerboseFrom Kevin Robertson's Powermad. The error "machine account quota exceeded" is the goal here: if the account gets created, something above didn't take.
07 Rollback
The realistic rollback is a provisioning flow you didn't know was riding the default. Restore the quota in seconds if you must:
Set-ADDomain -Identity (Get-ADDomain).distinguishedname -Replace @{"ms-DS-MachineAccountQuota"=10}Same command, value 10. The user right is rolled back by adding Authenticated Users back into the GPO and gpupdating the DCs.
But before you roll anything back, check what actually broke, because it's rarely the quota change's fault in the way it first appears. Error 8557 (ERROR_DS_MACHINE_ACCOUNT_QUOTA_EXCEEDED) in C:\Windows\debug\netsetup.log means a task sequence or helpdesk flow was leaning on the default; the fix is delegating that account properly, not reopening the door for everyone. Error 0xaac (2732, NERR_AccountReuseBlockedByPolicy) is the KB5020276 account-reuse hardening, a different control entirely; solve it with the "Domain controller: Allow computer account re-use during domain join" allow list or by joining with the creator account. And one odd one from the field: SQL Server Always On listeners and other WSFC roles need the cluster to create virtual computer objects, which can fail with the quota at zero; pre-stage those computer objects (or briefly raise the quota during cluster setup, then put it back).
Rolling back because a reimage got tedious is understandable; rolling back because it's easier than delegating is how the finding ends up on next year's pentest report too.
08 References
- Microsoft KB 243327: Default limit to number of workstations a user can join to the domain
- Microsoft Learn: Add workstations to domain (security policy setting)
- Microsoft Learn: Active Directory domain join permissions in Windows Server
- Microsoft KB5020276: Netjoin domain join hardening changes (CVE-2022-38042)
- Microsoft KB5008102: SAM hardening changes (CVE-2021-42278)
- Microsoft KB5008380: Authentication updates (CVE-2021-42287)
- NetSPI: MachineAccountQuota is USEFUL Sometimes
- Elad Shamir: Wagging the Dog (RBCD)
- The Hacker Recipes: MachineAccountQuota
- Shelltrail: AD domain (join)own accounts revisited
If I've got anything wrong here, or you've hit an edge case I haven't covered, do say: corrections and questions are always welcome :)
Ship the fix. Prove it’s closed.
If this runbook doesn’t fit your stack, send the CVE — an operator writes a verified path, usually within a business day. Or contribute your own and get co-authored credit.