
Prueba de concepto educativa para PrintNightmare (CVE-2021-1675/34527) con payload simulado no funcional, análisis del flujo de ataque, mapeo MITRE, guía de detección y pasos de remediación.
Tipo: Prueba de Concepto — Simulada (No Funcional) CVE: CVE-2021-1675 + CVE-2021-34527 CVSS: 7.8 (LPE) / 8.8 (RCE) Alias: PrintNightmare Parcheado: Junio/Julio 2021 — KB5004945 Añadido al CISA KEV: Julio 2021
⚠️ El payload de este PoC es explícitamente ficticio y no malicioso — solo 4 bytes de cabecera DCE/RPC seguidos del nombre de la función en ASCII. No ejecuta código, no instala controladores, no eleva privilegios. Uso exclusivo con fines de aprendizaje y desarrollo de detecciones.
Developed by: HKK$ cat ./vulnerability_summary.txtCVE-2021-1675, conocido como PrintNightmare, es una vulnerabilidad crítica de Ejecución Remota de Código y Escalada Local de Privilegios en el servicio Windows Print Spooler. La falla permite a los atacantes ejecutar código arbitrario con privilegios SYSTEM explotando la función RpcAddPrinterDriverEx(), utilizada para la instalación remota de controladores de impresora sin una validación adecuada del control de acceso.
Originalmente clasificada como LPE (CVSS 7.8) y parcheada en el Patch Tuesday de junio de 2021, Microsoft reclasificó la vulnerabilidad como RCE (CVSS 8.8) el 21 de junio. Para evitar confusiones, el vector RCE recibió un nuevo identificador, CVE-2021-34527 — ambos son comúnmente llamados PrintNightmare.
$ cat ./timeline.txtJun 08, 2021 Microsoft publica el parche inicial en el Patch Tuesday — CVE-2021-1675 (LPE, CVSS 7.8)
Jun 21, 2021 Microsoft reclasifica como RCE (CVSS 8.8)
Jun 29, 2021 Investigadores publican el PoC accidentalmente — creyendo que era la misma vuln ya parcheada
Jul 01, 2021 Se asigna CVE-2021-34527 para el vector RCE — distinto del LPE original
Jul 02, 2021 Microsoft lanza parche de emergencia out-of-band: KB5004945
Jul 2021 CISA lo añade al Known Exploited Vulnerabilities Catalog
Explotación activa por grupos de ransomware (Vice Society, Magniber, etc.)
$ cat ./architecture.txt┌──────────────────────────────────────────────────────────────────────────┐
│ PRINTNIGHTMARE — ATTACK FLOW │
│ │
│ ATACANTE (usuario autenticado) WINDOWS PRINT SPOOLER │
│ (spoolsv.exe) │
│ 1. Autenticarse con cualquier ┌────────────────────────────┐ │
│ cuenta de dominio válida │ Se ejecuta como SYSTEM │ │
│ │ │ Activo por defecto en todos │ │
│ 2. Conectarse vía RPC al │ los Windows, incluidos DCs │ │
│ named pipe \pipe\spoolss └──────────────┬─────────────┘ │
│ │ │ │
│ 3. Llamar a RpcAddPrinterDriverEx() │ │
│ con ruta a DLL maliciosa ──────────────────────►│ │
│ (UNC: \\attacker\share\evil.dll) │ │
│ ┌────────────▼────────────┐ │
│ │ Print Spooler carga el │ │
│ │ controlador (DLL) como │ │
│ │ SYSTEM sin verificar │ │
│ │ origen o integridad │ │
│ └────────────┬────────────┘ │
│ │ │
│ ◄── RCE / LPE como SYSTEM ───────────────────────────┘ │
│ Nuevo usuario admin, reverse shell, │
│ despliegue de ransomware, etc. │
│ │
│ ───────────────────────────────────────────────────────────────────── │
│ ESTE POC: solo TCP connect + 25 bytes → sin RPC real → sin exploit │
└──────────────────────────────────────────────────────────────────────────┘
$ cat ./design_decisions.mdfake_rpc_payload = b"\x05\x00\x0b\x03RpcAddPrinterDriverEx"
Este payload tiene 25 bytes y demuestra dos conceptos simultáneamente:
Bytes 0-3: Cabecera DCE/RPC legítima
Bytes 4-24: Nombre de la función en ASCII
RpcAddPrinterDriverEx — el nombre de la función vulnerable, en texto plano.
¿Por qué este payload no funciona como exploit real?
Un BIND RPC legítimo requeriría, después del header de 4 bytes:
- max_xmit_frag (2 bytes)
- max_recv_frag (2 bytes)
- assoc_group_id (4 bytes)
- num_ctx_items (1 byte)
- context_elem[] → UUID de interfaz MS-RPRN:
{12345678-1234-ABCD-EF00-0123456789AB}
- transfer_syntaxes → UUID NDR
Sin esta estructura, Windows rechaza el paquete inmediatamente. El payload es, efectivamente, solo una aserción de conectividad — "¿puedo alcanzar el puerto 445 con este payload ficticio?".
sock.connect((target_ip, 445))
¿Por qué 445 y no 135 (RPC Endpoint Mapper)?
PrintNightmare usa el named pipe SMB \pipe\spoolss como transporte — no el RPC directo. El flujo real es:
1. TCP connect → puerto 445 (SMB)
2. SMB negotiate + session setup (autenticación NTLM/Kerberos)
3. Tree connect → IPC$
4. Named pipe open → \pipe\spoolss
5. DCE/RPC BIND → interfaz MS-RPRN
6. Llamada a RpcAddPrinterDriverEx() con NDR marshaling
El PoC simula solo el paso 1 — la conexión TCP inicial — sin implementar los pasos 2-6.
sock.settimeout(5): el timeout de 5 segundos evita que el PoC se quede bloqueado en hosts que no responden. Útil para escaneo rápido de disponibilidad del puerto.
La causa raíz en ambos es la misma: la función RpcAddPrinterDriverEx() no valida el origen de los archivos de controlador, no impone restricciones de privilegio adecuadas para la instalación de controladores, y no verifica la autenticidad o integridad de las DLL que se están cargando.
$ cat ./mitre_mapping.ymltactic: Initial Access / Lateral Movement
- T1210 # Exploitation of Remote Services
# Llamada RPC vía \pipe\spoolss a host remoto
# Requiere credencial de dominio válida
tactic: Privilege Escalation
- T1068 # Exploitation for Privilege Escalation
# usuario común → SYSTEM vía Print Spooler
# CVE-2021-1675 (LPE): proceso local eleva a SYSTEM
tactic: Execution
- T1569.002 # System Services: Service Execution
# DLL maliciosa cargada por spoolsv.exe como SYSTEM
# Equivalente a ejecución de código vía servicio de Windows
- T1055 # Process Injection
# DLL inyectada en el contexto del proceso spoolsv.exe (SYSTEM)
tactic: Persistence
- T1547.012 # Boot or Logon Autostart: Print Processors
# Controlador registrado persiste entre reinicios
# Almacenado en: HKLM\SYSTEM\CurrentControlSet\Control\Print\
tactic: Defense Evasion
- T1036.005 # Masquerading: Match Legitimate Name or Location
# DLL maliciosa nombrada como controlador legítimo (ej: Canon_XP.dll)
$ cat ./detection_opportunities.md# Event ID 808 — Print Spooler falló al cargar DLL sospechosa
# Fuente: Microsoft-Windows-PrintService/Admin
Condición:
EventID: 808
Log: Microsoft-Windows-PrintService/Admin
Level: Error
Description CONTAINS: "failed to load a plug-in module"
Evidencia real (observed in-the-wild):
"The print spooler failed to load a plug-in module
C:\Windows\system32\spool\DRIVERS\x64\3\svch0st.dll"
# Typosquatting de svchost.dll → DLL maliciosa
# Event ID 316 — Controlador instalado vía RpcAddPrinterDriverEx
# Fuente: Microsoft-Windows-PrintService/Admin
Condición:
EventID: 316
Log: Microsoft-Windows-PrintService/Admin
Message CONTAINS: "RpcAddPrinterDriverEx"
OR
Message CONTAINS: "\\\\*\\*" # Ruta UNC → DLL remota
# Proceso hijo sospechoso de Print Spooler
EventID: 1 (Process Creation)
Condición:
ParentImage: C:\Windows\System32\spoolsv.exe
Image: cmd.exe O powershell.exe O wscript.exe O mshta.exe
Severidad: CRÍTICA — spoolsv no debería generar shells
# DLL cargada desde ruta no estándar
EventID: 7 (Image Loaded)
Condición:
Image: C:\Windows\System32\spoolsv.exe
ImageLoaded NOT STARTS WITH:
- C:\Windows\System32\spool\DRIVERS\
- C:\Windows\System32\
- C:\Windows\SysWOW64\
Severidad: ALTA
Para detección a nivel de red, monitorear named pipes SMB: la presencia de \pipe\spoolss combinada con las operaciones RpcEnumPrinterDrivers o RpcAddPrinterDriverEx son indicadores directos de explotación de PrintNightmare.
# Regla conceptual 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.mdOPCIÓN 1 — Deshabilitar Print Spooler (si la impresión no es necesaria)
PowerShell:
Stop-Service -Name Spooler -Force
Set-Service -Name Spooler -StartupType Disabled
OPCIÓN 2 — Bloquear impresión remota vía Group Policy
Computer Configuration → Administrative Templates → Printers
→ "Allow Print Spooler to accept client connections": DISABLED
Esto deshabilita solo el vector remoto, manteniendo la impresión local
OPCIÓN 3 — Aplicar parches (obligatorio independientemente de las opciones anteriores)
KB5004945 → parche out-of-band Julio 2021
+ Parches acumulativos posteriores
VERIFICACIÓN POST-PARCHE — El registro aún puede dejar vulnerable:
REG QUERY "HKLM\Software\Policies\Microsoft\Windows NT\Printers\PointAndPrint"
Si NoWarningNoElevationOnInstall=1 O UpdatePromptSettings=0 → AÚN VULNERABLE
Corregir: establecer ambos valores en 0 o eliminar las claves
PRIORIDAD ESPECIAL: Domain Controllers
Los DCs ejecutan Print Spooler por defecto
Comprometer un DC vía PrintNightmare = compromiso completo del dominio AD
$ cat ./usage.sh# Instalar dependencia (socket es stdlib)
python --version # Python 3.x, sin pip necesario
# Editar la IP objetivo en el script (solo en lab autorizado)
# simulate_printnightmare_attack("192.168.1.xxx")
python poc_cve_2021_1675.py
# Salida esperada si el puerto 445 es accesible:
[+] Payload enviado a 192.168.1.117
# Salida esperada si el puerto está cerrado/filtrado:
[-] Error al conectar: [Errno 111] Connection refused
# o
[-] Error al conectar: timed out
Qué indica esta salida: solo que el puerto 445 es accesible. No confirma vulnerabilidad — para eso, sería necesario un RPC BIND real + verificación de la versión del parche.
$ cat ./poc_vs_real_exploit.mdComparación explícita entre el PoC simulado y un exploit real.
$ cat ./lessons_learned.txt[+] Print Spooler activo en DCs por defecto es el escenario más crítico — SYSTEM en DC = game over
[+] Los named pipes SMB como transporte RPC son un vector subestimado en defensas perimeter-focused
[+] DCE/RPC es un protocolo complejo — entender la estructura de bind/call ayuda a crear firmas
[+] CVE publicada ≠ parche aplicado — semanas después del parche, la mayoría de los entornos aún eran vulnerables
[+] Las claves de registro PointAndPrint pueden reintroducir la vuln incluso después del parche — control post-parche crítico
[-] Este PoC solo verifica conectividad TCP — no valida si el sistema está realmente parcheado
[-] Socket puro sin SMB no puede negociar autenticación — limitación fundamental del enfoque
[-] settimeout(5) puede generar falsos negativos en redes lentas — considerar timeout parametrizable
[→] Mejoras: usar impacket para RPC real, verificar banner SMB para fingerprint de versión del SO,
probar KB aplicado vía consulta de registro remota
CVE Research · PrintNightmare · Patched July 2021 · CISA KEV · Simulated payload only
| Byte | Valor | Significado |
|---|
\x05 | 5 | Versión del protocolo DCE/RPC (versión 5 — estándar de Windows) |
\x00 | 0 | Versión menor 0 |
\x0b | 11 | Tipo de PDU: BIND — primer paso de la negociación RPC |
\x03 | 3 | Flags: `PFC_FIRST_FRAG(0x01) |
| Aspecto | CVE-2021-1675 | CVE-2021-34527 |
|---|
| Vector | Local (LPE) | Remoto (RCE) |
| CVSS | 7.8 | 8.8 |
| Autenticación | Cuenta local | Cuenta de dominio autenticada |
| Parche | Junio 2021 (Patch Tuesday) | Julio 2021 (out-of-band KB5004945) |
| Función vulnerable | RpcAddPrinterDriverEx | RpcAddPrinterDriverEx |
| Escenario | Escalada local | RCE remoto vía SMB named pipe |
| Componente | Este PoC | Exploit Real |
|---|
| Conexión | Socket TCP puerto 445 | Sesión SMB + Tree connect IPC$ |
| Autenticación | Ninguna | NTLM o Kerberos (cuenta de dominio) |
| Named pipe | No implementado | \pipe\spoolss |
| RPC BIND | Falso (4 bytes + ASCII) | DCE/RPC BIND con UUID MS-RPRN |
| Función llamada | No llamada | RpcAddPrinterDriverEx() vía NDR |
| Ruta DLL | No enviada | UNC: \\attacker\share\evil.dll |
| Resultado | Impresión en consola | RCE como SYSTEM / LPE |
| Detección | Casi nula | EventID 808, 316, Sysmon 1/7 |