类型: 概念验证 — 模拟(非功能性) CVE: CVE-2021-1675 + CVE-2021-34527 CVSS: 7.8(LPE)/ 8.8(RCE) 别名: PrintNightmare 已修补: 2021年6月/7月 — KB5004945 已加入 CISA KEV: 2021年7月
⚠️ 此 PoC 的载荷明确为虚构且非恶意 — 仅为 4 字节的 DCE/RPC 头,后跟 ASCII 格式的函数名称。它不执行代码、不安装驱动程序、不提升权限。仅用于学习和检测开发目的。
Developed by: HKK$ cat ./vulnerability_summary.txtCVE-2021-1675,即 PrintNightmare,是 Windows Print Spooler 服务中的一个严重远程代码执行和本地权限提升漏洞。该缺陷允许攻击者通过利用 RpcAddPrinterDriverEx() 函数(用于远程安装打印机驱动程序,但缺乏适当的访问控制验证)以 SYSTEM 权限执行任意代码。
该漏洞最初被归类为 LPE(CVSS 7.8),并于 2021 年 6 月的补丁星期二中修复,但微软于 6 月 21 日将其重新归类为 RCE(CVSS 8.8)。为避免混淆,RCE 向量被分配了新的标识符 CVE-2021-34527 — 两者通常都被称为 PrintNightmare。
$ cat ./timeline.txt2021年6月8日 微软在补丁星期二发布初始补丁 — CVE-2021-1675(LPE,CVSS 7.8)
2021年6月21日 微软重新归类为 RCE(CVSS 8.8)
2021年6月29日 研究人员意外发布 PoC — 误以为这是已修补的同一漏洞
2021年7月1日 为 RCE 向量分配 CVE-2021-34527 — 与原始 LPE 不同
2021年7月2日 微软发布紧急带外补丁:KB5004945
2021年7月 CISA 将其添加到已知被利用漏洞目录
勒索软件团伙(Vice Society、Magniber 等)正在积极利用
$ cat ./architecture.txt┌──────────────────────────────────────────────────────────────────────────┐
│ PRINTNIGHTMARE — 攻击流程 │
│ │
│ 攻击者(已认证用户) WINDOWS PRINT SPOOLER │
│ (spoolsv.exe) │
│ 1. 使用任意有效域账户 ┌────────────────────────────┐ │
│ 进行身份验证 │ 以 SYSTEM 身份运行 │ │
│ │ │ 默认在所有 Windows 上启用 │ │
│ 2. 通过 RPC 连接到 │ 包括域控制器 │ │
│ 命名管道 \pipe\spoolss └──────────────┬─────────────┘ │
│ │ │ │
│ 3. 调用 RpcAddPrinterDriverEx() │ │
│ 并传入恶意 DLL 路径 ──────────────────────────►│ │
│ (UNC: \\attacker\share\evil.dll) │ │
│ ┌────────▼────────────┐ │
│ │ Print Spooler 以 │ │
│ │ SYSTEM 身份加载驱动 │ │
│ │ (DLL),不验证来源 │ │
│ │ 或完整性 │ │
│ └────────┬────────────┘ │
│ │ │
│ ◄── 以 SYSTEM 身份实现 RCE / LPE ─────────────────┘ │
│ 新建管理员用户、反向 Shell、 │
│ 部署勒索软件等。 │
│ │
│ ───────────────────────────────────────────────────────────────────── │
│ 此 PoC:仅 TCP 连接 + 25 字节 → 无真实 RPC → 无漏洞利用 │
└──────────────────────────────────────────────────────────────────────────┘
$ cat ./design_decisions.mdfake_rpc_payload = b"\x05\x00\x0b\x03RpcAddPrinterDriverEx"
此载荷为 25 字节,同时演示两个概念:
字节 0-3:合法的 DCE/RPC 头
| 字节 | 值 | 含义 |
|---|---|---|
\x05 | 5 | DCE/RPC 协议版本(版本 5 — Windows 标准) |
\x00 | 0 | 次版本号 0 |
\x0b | 11 | PDU 类型:BIND — RPC 协商的第一步 |
\x03 | 3 | 标志:`PFC_FIRST_FRAG(0x01) |
字节 4-24:ASCII 格式的函数名称
RpcAddPrinterDriverEx — 易受攻击的函数名称,以纯文本形式呈现。
为什么此载荷不能作为真正的漏洞利用?
合法的 RPC BIND 在 4 字节头之后还需要:
- max_xmit_frag (2 字节)
- max_recv_frag (2 字节)
- assoc_group_id (4 字节)
- num_ctx_items (1 字节)
- context_elem[] → MS-RPRN 接口 UUID:
{12345678-1234-ABCD-EF00-0123456789AB}
- transfer_syntaxes → NDR UUID
没有此结构,Windows 会立即拒绝该数据包。实际上,此载荷仅是一个连接性断言 — “我能否使用此虚构载荷到达 445 端口?”。
sock.connect((target_ip, 445))
为什么是 445 而不是 135(RPC 端点映射器)?
PrintNightmare 使用 SMB 命名管道 \pipe\spoolss 作为传输 — 而非直接的 RPC。真实流程如下:
1. TCP 连接 → 445 端口(SMB)
2. SMB 协商 + 会话建立(NTLM/Kerberos 身份验证)
3. 树连接 → IPC$
4. 打开命名管道 → \pipe\spoolss
5. DCE/RPC BIND → MS-RPRN 接口
6. 使用 NDR 封送处理调用 RpcAddPrinterDriverEx()
PoC 仅模拟步骤 1 — 初始 TCP 连接 — 而不实现步骤 2-6。
sock.settimeout(5): 5 秒超时防止 PoC 在无响应的主机上阻塞。适用于快速扫描端口可用性。
| 方面 | CVE-2021-1675 | CVE-2021-34527 |
|---|---|---|
| 向量 | 本地(LPE) | 远程(RCE) |
| CVSS | 7.8 | 8.8 |
| 身份验证 | 本地账户 | 已认证的域账户 |
| 补丁 | 2021年6月(补丁星期二) | 2021年7月(带外 KB5004945) |
| 易受攻击的函数 | RpcAddPrinterDriverEx | RpcAddPrinterDriverEx |
| 场景 | 本地提权 | 通过 SMB 命名管道进行远程 RCE |
两者的根本原因相同:RpcAddPrinterDriverEx() 函数未能验证驱动程序文件的来源,未对驱动程序安装施加适当的权限限制,并且不检查所加载 DLL 的真实性或完整性。
$ cat ./mitre_mapping.ymltactic: Initial Access / Lateral Movement
- T1210 # Exploitation of Remote Services
# 通过 \pipe\spoolss 对远程主机进行 RPC 调用
# 需要有效的域凭据
tactic: Privilege Escalation
- T1068 # Exploitation for Privilege Escalation
# 普通用户 → 通过 Print Spooler 获取 SYSTEM
# CVE-2021-1675 (LPE):本地进程提升至 SYSTEM
tactic: Execution
- T1569.002 # System Services: Service Execution
# 恶意 DLL 由 spoolsv.exe 以 SYSTEM 身份加载
# 等同于通过 Windows 服务执行代码
- T1055 # Process Injection
# DLL 注入到 spoolsv.exe(SYSTEM)进程上下文中
tactic: Persistence
- T1547.012 # Boot or Logon Autostart: Print Processors
# 注册的驱动程序在重启后持续存在
# 存储于:HKLM\SYSTEM\CurrentControlSet\Control\Print\
tactic: Defense Evasion
- T1036.005 # Masquerading: Match Legitimate Name or Location
# 恶意 DLL 命名为合法驱动程序(例如:Canon_XP.dll)
$ cat ./detection_opportunities.md# 事件 ID 808 — Print Spooler 加载可疑 DLL 失败
# 来源:Microsoft-Windows-PrintService/Admin
条件:
EventID: 808
Log: Microsoft-Windows-PrintService/Admin
Level: Error
Description CONTAINS: "failed to load a plug-in module"
真实证据(野外观察):
"The print spooler failed to load a plug-in module
C:\Windows\system32\spool\DRIVERS\x64\3\svch0st.dll"
# svchost.dll 的仿冒拼写 → 恶意 DLL
# 事件 ID 316 — 通过 RpcAddPrinterDriverEx 安装驱动程序
# 来源:Microsoft-Windows-PrintService/Admin
条件:
EventID: 316
Log: Microsoft-Windows-PrintService/Admin
Message CONTAINS: "RpcAddPrinterDriverEx"
OR
Message CONTAINS: "\\\\*\\*" # UNC 路径 → 远程 DLL
# Print Spooler 的可疑子进程
EventID: 1 (Process Creation)
条件:
ParentImage: C:\Windows\System32\spoolsv.exe
Image: cmd.exe OU powershell.exe OU wscript.exe OU mshta.exe
严重性:严重 — spoolsv 不应生成 shell
# 从非标准路径加载的 DLL
EventID: 7 (Image Loaded)
条件:
Image: C:\Windows\System32\spoolsv.exe
ImageLoaded NOT STARTS WITH:
- C:\Windows\System32\spool\DRIVERS\
- C:\Windows\System32\
- C:\Windows\SysWOW64\
严重性:高
对于网络层面的检测,监控 SMB 命名管道:\pipe\spoolss 的存在与 RpcEnumPrinterDrivers 或 RpcAddPrinterDriverEx 操作相结合,是 PrintNightmare 被利用的直接指标。
# 概念性 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.md选项 1 — 禁用 Print Spooler(如果不需要打印功能)
PowerShell:
Stop-Service -Name Spooler -Force
Set-Service -Name Spooler -StartupType Disabled