类型: 概念验证 — 模拟(非功能性) 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 头
字节 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 在无响应的主机上阻塞。适用于快速扫描端口可用性。
两者的根本原因相同: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
选项 2 — 通过组策略阻止远程打印
Computer Configuration → Administrative Templates → Printers
→ "Allow Print Spooler to accept client connections": DISABLED
这仅禁用远程向量,保留本地打印功能
选项 3 — 应用补丁(无论上述选项如何,均为强制要求)
KB5004945 → 2021年7月带外补丁
+ 后续累积更新
补丁后验证 — 注册表仍可能使系统易受攻击:
REG QUERY "HKLM\Software\Policies\Microsoft\Windows NT\Printers\PointAndPrint"
如果 NoWarningNoElevationOnInstall=1 或 UpdatePromptSettings=0 → 仍然易受攻击
修复:将两个值均设为 0 或删除这些键
特别优先:域控制器
域控制器默认运行 Print Spooler
通过 PrintNightmare 攻陷域控制器 = 整个 AD 域完全沦陷
$ cat ./usage.sh# 安装依赖(socket 为标准库)
python --version # Python 3.x,无需 pip
# 在脚本中编辑目标 IP(仅在授权的实验环境中)
# simulate_printnightmare_attack("192.168.1.xxx")
python poc_cve_2021_1675.py
# 如果 445 端口可访问,预期输出:
[+] Payload enviado para 192.168.1.117
# 如果端口关闭/被过滤,预期输出:
[-] Erro ao conectar: [Errno 111] Connection refused
# 或
[-] Erro ao conectar: timed out
此输出表明什么: 仅表明 445 端口可访问。并不确认存在漏洞 — 为此,需要真实的 RPC BIND 以及补丁版本验证。
$ cat ./poc_vs_real_exploit.md模拟 PoC 与真实漏洞利用之间的明确比较。
$ cat ./lessons_learned.txt[+] Print Spooler 默认在域控制器上运行是最关键的场景 — 在 DC 上获取 SYSTEM = 游戏结束
[+] 作为 RPC 传输的 SMB 命名管道在 perimeter-focused 防御中是被低估的向量
[+] DCE/RPC 是复杂协议 — 理解 bind/call 结构有助于创建签名
[+] 已发布的 CVE ≠ 已应用的补丁 — 补丁发布数周后,大多数环境仍然易受攻击
[+] PointAndPrint 注册表键即使在补丁后也可能重新引入漏洞 — 补丁后控制至关重要
[-] 此 PoC 仅验证 TCP 连接性 — 不验证系统是否实际已修补
[-] 无 SMB 的纯 socket 无法协商身份验证 — 该方法的根本限制
[-] settimeout(5) 在慢速网络中可能产生误报 — 考虑使用可参数化的超时
[→] 改进:使用 impacket 进行真实 RPC,检查 SMB 横幅以识别操作系统版本,
通过远程注册表查询测试已应用的 KB
CVE Research · PrintNightmare · Patched July 2021 · CISA KEV · Simulated payload only
| 字节 | 值 | 含义 |
|---|
\x05 | 5 | DCE/RPC 协议版本(版本 5 — Windows 标准) |
\x00 | 0 | 次版本号 0 |
\x0b | 11 | PDU 类型:BIND — RPC 协商的第一步 |
\x03 | 3 | 标志:`PFC_FIRST_FRAG(0x01) |
| 方面 | CVE-2021-1675 | CVE-2021-34527 |
|---|
| 向量 | 本地(LPE) | 远程(RCE) |
| CVSS | 7.8 | 8.8 |
| 身份验证 | 本地账户 | 已认证的域账户 |
| 补丁 | 2021年6月(补丁星期二) | 2021年7月(带外 KB5004945) |
| 易受攻击的函数 | RpcAddPrinterDriverEx | RpcAddPrinterDriverEx |
| 场景 | 本地提权 | 通过 SMB 命名管道进行远程 RCE |
| 组件 | 此 PoC | 真实漏洞利用 |
|---|
| 连接 | TCP socket 445 端口 | SMB 会话 + Tree connect IPC$ |
| 身份验证 | 无 | NTLM 或 Kerberos(域账户) |
| 命名管道 | 未实现 | \pipe\spoolss |
| RPC BIND | 伪造(4 字节 + ASCII) | 带 MS-RPRN UUID 的 DCE/RPC BIND |
| 调用的函数 | 未调用 | 通过 NDR 调用 RpcAddPrinterDriverEx() |
| DLL 路径 | 未发送 | UNC:\\attacker\share\evil.dll |
| 结果 | 控制台输出 | 以 SYSTEM 身份 RCE / LPE |
| 检测 | 几乎为零 | EventID 808、316、Sysmon 1/7 |