
Proof-of-concept educativo per PrintNightmare (CVE-2021-1675/34527) con payload simulato non funzionale, analisi del flusso di attacco, mappatura MITRE, indicazioni di rilevamento e passaggi di remediation.
Tipo: Proof of Concept — Simulato (Non Funzionale) CVE: CVE-2021-1675 + CVE-2021-34527 CVSS: 7.8 (LPE) / 8.8 (RCE) Alias: PrintNightmare Patchato: Giugno/Luglio 2021 — KB5004945 Aggiunto al CISA KEV: Luglio 2021
⚠️ Il payload di questo PoC è esplicitamente fittizio e non dannoso — solo 4 byte di header DCE/RPC seguiti dal nome della funzione in ASCII. Non esegue codice, non installa driver, non eleva privilegi. Uso esclusivo per scopi di apprendimento e sviluppo di rilevamenti.
Developed by: HKK$ cat ./vulnerability_summary.txtCVE-2021-1675, noto come PrintNightmare, è una vulnerabilità critica di Remote Code Execution e Local Privilege Escalation nel servizio Windows Print Spooler. La falla consente agli attaccanti di eseguire codice arbitrario con privilegi SYSTEM sfruttando la funzione RpcAddPrinterDriverEx(), usata per l'installazione remota di driver di stampante senza un'adeguata validazione del controllo di accesso.
Originariamente classificata come LPE (CVSS 7.8) e patchata nel Patch Tuesday di giugno 2021, Microsoft ha riclassificato la vulnerabilità come RCE (CVSS 8.8) il 21 giugno. Per evitare confusione, il vettore RCE ha ricevuto un nuovo identificatore, CVE-2021-34527 — entrambi sono comunemente chiamati PrintNightmare.
$ cat ./timeline.txtGiu 08, 2021 Microsoft pubblica la patch iniziale nel Patch Tuesday — CVE-2021-1675 (LPE, CVSS 7.8)
Giu 21, 2021 Microsoft riclassifica come RCE (CVSS 8.8)
Giu 29, 2021 I ricercatori pubblicano il PoC accidentalmente — credendo fosse la stessa vuln già patchata
Lug 01, 2021 CVE-2021-34527 assegnato per il vettore RCE — distinto dall'LPE originale
Lug 02, 2021 Microsoft rilascia patch d'emergenza out-of-band: KB5004945
Lug 2021 CISA aggiunge al Known Exploited Vulnerabilities Catalog
Sfruttamento attivo da parte di gruppi ransomware (Vice Society, Magniber, ecc.)
$ cat ./architecture.txt┌──────────────────────────────────────────────────────────────────────────┐
│ PRINTNIGHTMARE — ATTACK FLOW │
│ │
│ ATTACCANTE (utente autenticato) WINDOWS PRINT SPOOLER │
│ (spoolsv.exe) │
│ 1. Autenticarsi con qualsiasi ┌────────────────────────────┐│
│ account di dominio valido │ Gira come SYSTEM ││
│ │ │ Attivo di default su tutti││
│ 2. Connettersi via RPC al │ i Windows, inclusi i DC ││
│ named pipe \pipe\spoolss └──────────────┬─────────────┘│
│ │ │ │
│ 3. Chiamare RpcAddPrinterDriverEx() │ │
│ con path verso DLL dannosa ──────────────────────────►│ │
│ (UNC: \\attacker\share\evil.dll) │ │
│ ┌──────────────▼────────────┐ │
│ │ Print Spooler carica il │ │
│ │ driver (DLL) come SYSTEM │ │
│ │ senza verificare origine │ │
│ │ o integrità │ │
│ └──────────────┬────────────┘ │
│ │ │
│ ◄── RCE / LPE come SYSTEM ──────────────────────────────┘ │
│ Nuovo utente admin, reverse shell, │
│ distribuzione ransomware, ecc. │
│ │
│ ───────────────────────────────────────────────────────────────────── │
│ QUESTO POC: solo TCP connect + 25 byte → nessun RPC reale → nessun exploit
└──────────────────────────────────────────────────────────────────────────┘
$ cat ./design_decisions.mdfake_rpc_payload = b"\x05\x00\x0b\x03RpcAddPrinterDriverEx"
Questo payload ha 25 byte e dimostra due concetti simultaneamente:
Byte 0-3: Header DCE/RPC legittimo
Byte 4-24: Nome della funzione in ASCII
RpcAddPrinterDriverEx — il nome della funzione vulnerabile, in testo semplice.
Perché questo payload non funziona come exploit reale?
Un BIND RPC legittimo richiederebbe, dopo l'header di 4 byte:
- max_xmit_frag (2 byte)
- max_recv_frag (2 byte)
- assoc_group_id (4 byte)
- num_ctx_items (1 byte)
- context_elem[] → Interface UUID del MS-RPRN:
{12345678-1234-ABCD-EF00-0123456789AB}
- transfer_syntaxes → NDR UUID
Senza questa struttura, Windows rifiuta il pacchetto immediatamente. Il payload è, effettivamente, solo un'asserzione di connettività — "riesco a raggiungere la porta 445 con questo payload fittizio?".
sock.connect((target_ip, 445))
Perché 445 e non 135 (RPC Endpoint Mapper)?
PrintNightmare usa il SMB named pipe \pipe\spoolss come trasporto — non l'RPC diretto. Il flusso reale è:
1. TCP connect → porta 445 (SMB)
2. SMB negotiate + session setup (autenticazione NTLM/Kerberos)
3. Tree connect → IPC$
4. Named pipe open → \pipe\spoolss
5. DCE/RPC BIND → interfaccia MS-RPRN
6. Chiamata RpcAddPrinterDriverEx() con NDR marshaling
Il PoC simula solo il passo 1 — la connessione TCP iniziale — senza implementare i passi 2-6.
sock.settimeout(5): il timeout di 5 secondi impedisce al PoC di bloccarsi su host che non rispondono. Utile per uno scanning rapido della disponibilità della porta.
La causa principale in entrambi è la stessa: la funzione RpcAddPrinterDriverEx() non riesce a validare l'origine dei file driver, non impone adeguate restrizioni di privilegio per l'installazione dei driver e non verifica l'autenticità o l'integrità delle DLL che vengono caricate.
$ cat ./mitre_mapping.ymltactic: Initial Access / Lateral Movement
- T1210 # Exploitation of Remote Services
# Chiamata RPC via \pipe\spoolss verso host remoto
# Richiede credenziale di dominio valida
tactic: Privilege Escalation
- T1068 # Exploitation for Privilege Escalation
# utente comune → SYSTEM via Print Spooler
# CVE-2021-1675 (LPE): processo locale eleva a SYSTEM
tactic: Execution
- T1569.002 # System Services: Service Execution
# DLL dannosa caricata da spoolsv.exe come SYSTEM
# Equivalente a esecuzione di codice via servizio Windows
- T1055 # Process Injection
# DLL iniettata nel contesto del processo spoolsv.exe (SYSTEM)
tactic: Persistence
- T1547.012 # Boot or Logon Autostart: Print Processors
# Driver registrato persiste tra i riavvii
# Archiviato in: HKLM\SYSTEM\CurrentControlSet\Control\Print\
tactic: Defense Evasion
- T1036.005 # Masquerading: Match Legitimate Name or Location
# DLL dannosa nominata come driver legittimo (es: Canon_XP.dll)
$ cat ./detection_opportunities.md# Event ID 808 — Print Spooler non è riuscito a caricare DLL sospetta
# Fonte: Microsoft-Windows-PrintService/Admin
Condizione:
EventID: 808
Log: Microsoft-Windows-PrintService/Admin
Level: Error
Description CONTAINS: "failed to load a plug-in module"
Evidenza reale (observed in-the-wild):
"The print spooler failed to load a plug-in module
C:\Windows\system32\spool\DRIVERS\x64\3\svch0st.dll"
# Typosquatting di svchost.dll → DLL dannosa
# Event ID 316 — Driver installato via RpcAddPrinterDriverEx
# Fonte: Microsoft-Windows-PrintService/Admin
Condizione:
EventID: 316
Log: Microsoft-Windows-PrintService/Admin
Message CONTAINS: "RpcAddPrinterDriverEx"
OR
Message CONTAINS: "\\\\*\\*" # Path UNC → DLL remota
# Processo figlio sospetto del Print Spooler
EventID: 1 (Process Creation)
Condizione:
ParentImage: C:\Windows\System32\spoolsv.exe
Image: cmd.exe OPPURE powershell.exe OPPURE wscript.exe OPPURE mshta.exe
Severità: CRITICA — spoolsv non dovrebbe generare shell
# DLL caricata da path non standard
EventID: 7 (Image Loaded)
Condizione:
Image: C:\Windows\System32\spoolsv.exe
ImageLoaded NOT STARTS WITH:
- C:\Windows\System32\spool\DRIVERS\
- C:\Windows\System32\
- C:\Windows\SysWOW64\
Severità: ALTA
Per il rilevamento a livello di rete, monitorare i named pipe SMB: la presenza di \pipe\spoolss combinata con le operazioni RpcEnumPrinterDrivers o RpcAddPrinterDriverEx sono indicatori diretti dello sfruttamento di PrintNightmare.
# Regola concettuale Zeek / Suricata:
alert smb any any -> $SERVERS 445 (
msg:"PrintNightmare RpcAddPrinterDriverEx via SMB";
content:"|5c 70 69 70 65 5c 73 70 6f 6f 6c 73 73|"; # \pipe\spoolss
content:"RpcAddPrinterDriverEx";
sid:2021001675;
)
$ cat ./remediation.mdOPZIONE 1 — Disabilitare Print Spooler (se la stampa non è necessaria)
PowerShell:
Stop-Service -Name Spooler -Force
Set-Service -Name Spooler -StartupType Disabled
OPZIONE 2 — Bloccare la stampa remota tramite Group Policy
Computer Configuration → Administrative Templates → Printers
→ "Allow Print Spooler to accept client connections": DISABLED
Questo disabilita solo il vettore remoto, mantenendo la stampa locale
OPZIONE 3 — Applicare le patch (obbligatorio indipendentemente dalle opzioni sopra)
KB5004945 → patch out-of-band Luglio 2021
+ Patch cumulative successive
VERIFICA POST-PATCH — Il registry può ancora lasciare vulnerabile:
REG QUERY "HKLM\Software\Policies\Microsoft\Windows NT\Printers\PointAndPrint"
Se NoWarningNoElevationOnInstall=1 OPPURE UpdatePromptSettings=0 → ANCORA VULNERABILE
Correzione: impostare entrambi i valori a 0 o rimuovere le chiavi
PRIORITÀ SPECIALE: Domain Controllers
I DC eseguono Print Spooler di default
Compromettere un DC via PrintNightmare = compromissione completa del dominio AD
$ cat ./usage.sh# Installare la dipendenza (socket è stdlib)
python --version # Python 3.x, nessun pip necessario
# Modificare l'IP target nello script (solo in lab autorizzato)
# simulate_printnightmare_attack("192.168.1.xxx")
python poc_cve_2021_1675.py
# Output atteso se la porta 445 è accessibile:
[+] Payload inviato a 192.168.1.117
# Output atteso se la porta è chiusa/filtrata:
[-] Errore di connessione: [Errno 111] Connection refused
# oppure
[-] Errore di connessione: timed out
Cosa indica questo output: solo che la porta 445 è accessibile. Non conferma la vulnerabilità — per questo sarebbe necessario un RPC BIND reale + verifica della versione della patch.
$ cat ./poc_vs_real_exploit.mdConfronto esplicito tra il PoC simulato e un exploit reale.
$ cat ./lessons_learned.txt[+] Print Spooler attivo sui DC di default è lo scenario più critico — SYSTEM su DC = game over
[+] I named pipe SMB come trasporto RPC sono un vettore sottovalutato nelle difese perimeter-focused
[+] DCE/RPC è un protocollo complesso — capire la struttura di bind/call aiuta a creare firme
[+] CVE pubblicata ≠ patch applicata — settimane dopo la patch, la maggior parte degli ambienti era ancora vulnerabile
[+] Le chiavi registry PointAndPrint possono reintrodurre la vuln anche dopo la patch — controllo post-patch critico
[-] Questo PoC verifica solo la connettività TCP — non valida se il sistema è effettivamente patchato
[-] Socket puro senza SMB non può negoziare l'autenticazione — limitazione fondamentale dell'approccio
[-] settimeout(5) può generare falsi negativi su reti lente — considerare un timeout parametrizzabile
[→] Miglioramenti: usare impacket per RPC reale, verificare il banner SMB per il fingerprint della versione del SO,
testare la KB applicata tramite query registry remota
CVE Research · PrintNightmare · Patched July 2021 · CISA KEV · Simulated payload only
| Byte | Valore | Significato |
|---|
\x05 | 5 | Versione del protocollo DCE/RPC (versione 5 — standard Windows) |
\x00 | 0 | Minor version 0 |
\x0b | 11 | PDU Type: BIND — primo passo della negoziazione RPC |
\x03 | 3 | Flags: `PFC_FIRST_FRAG(0x01) |
| Aspetto | CVE-2021-1675 | CVE-2021-34527 |
|---|
| Vettore | Locale (LPE) | Remoto (RCE) |
| CVSS | 7.8 | 8.8 |
| Autenticazione | Account locale | Account di dominio autenticato |
| Patch | Giugno 2021 (Patch Tuesday) | Luglio 2021 (out-of-band KB5004945) |
| Funzione vulnerabile | RpcAddPrinterDriverEx | RpcAddPrinterDriverEx |
| Scenario | Escalation locale | RCE remoto via SMB named pipe |
| Componente | Questo PoC | Exploit Reale |
|---|
| Connessione | Socket TCP porta 445 | Sessione SMB + Tree connect IPC$ |
| Autenticazione | Nessuna | NTLM o Kerberos (account di dominio) |
| Named pipe | Non implementato | \pipe\spoolss |
| RPC BIND | Falso (4 byte + ASCII) | DCE/RPC BIND con UUID MS-RPRN |
| Funzione chiamata | Non chiamata | RpcAddPrinterDriverEx() via NDR |
| Path DLL | Non inviato | UNC: \\attacker\share\evil.dll |
| Risultato | Stampato su console | RCE come SYSTEM / LPE |
| Rilevamento | Quasi nullo | EventID 808, 316, Sysmon 1/7 |