
タイプ: 概念実証 — シミュレーション(非機能) CVE: CVE-2021-1675 + CVE-2021-34527 CVSS: 7.8 (LPE) / 8.8 (RCE) 別名: PrintNightmare パッチ適用: 2021年6月/7月 — KB5004945 CISA KEV に追加: 2021年7月
⚠️ このPoCのペイロードは明示的に架空かつ非悪意のものです — DCE/RPCヘッダーの4バイトとASCIIの関数名のみで構成されています。コードを実行せず、ドライバーをインストールせず、権限を昇格させません。学習および検知開発目的のみに使用します。
Developed by: HKK$ cat ./vulnerability_summary.txtCVE-2021-1675、通称 PrintNightmare は、Windows Print Spooler サービスにおける重大なリモートコード実行およびローカル権限昇格の脆弱性です。この欠陥により、攻撃者はアクセス制御の検証が不十分なプリンタードライバーのリモートインストールに使用される RpcAddPrinterDriverEx() 関数を悪用して、SYSTEM 権限で任意のコードを実行できます。
当初はLPE(CVSS 7.8)として分類され、2021年6月のPatch Tuesdayでパッチが適用されましたが、Microsoftは6月21日にこの脆弱性をRCE(CVSS 8.8)として再分類しました。混乱を避けるため、RCEベクターには新しい識別子 CVE-2021-34527 が割り当てられました — 両者は一般的に PrintNightmare と呼ばれています。
$ cat ./timeline.txt2021年6月8日 MicrosoftがPatch Tuesdayで初期パッチを公開 — CVE-2021-1675 (LPE, CVSS 7.8)
2021年6月21日 MicrosoftがRCE (CVSS 8.8) として再分類
2021年6月29日 研究者が誤ってPoCを公開 — 既にパッチ済みの同じ脆弱性と誤認
2021年7月1日 CVE-2021-34527 がRCEベクターに割り当て — 元のLPEとは別
2021年7月2日 Microsoftが緊急の帯域外パッチを公開: KB5004945
2021年7月 CISAが既知の悪用された脆弱性カタログに追加
ランサムウェアグループ(Vice Society、Magniberなど)による活発な悪用
$ cat ./architecture.txt┌──────────────────────────────────────────────────────────────────────────┐
│ PRINTNIGHTMARE — 攻撃フロー │
│ │
│ 攻撃者 (認証済みユーザー) WINDOWS PRINT SPOOLER │
│ (spoolsv.exe) │
│ 1. 任意の有効なドメインアカウントで ┌────────────────────────────┐ │
│ 認証 │ SYSTEMとして実行 │
│ │ │ 全Windowsでデフォルト有効 │ │
│ 2. named pipe \pipe\spoolss 経由で │ DCを含む │ │
│ RPC接続 └──────────────┬─────────────┘ │
│ │ │ │
│ 3. RpcAddPrinterDriverEx() を呼び出し │ │
│ 悪意のあるDLLへのパスを指定 ──────────────────────►│ │
│ (UNC: \\attacker\share\evil.dll) │ │
│ ┌────────────▼────────────┐ │
│ │ Print Spoolerがドライバー│ │
│ │ (DLL) をSYSTEMとして │ │
│ │ 読み込み。発信元や整合性 │ │
│ │ を検証しない │ │
│ └────────────┬────────────┘ │
│ │ │
│ ◄── SYSTEMとしてのRCE / LPE ──────────────────────────┘ │
│ 新しい管理者ユーザー、リバースシェル、 │
│ ランサムウェア展開など │
│ │
│ ───────────────────────────────────────────────────────────────────── │
│ このPoC: TCP接続 + 25バイトのみ → 実際のRPCなし → エクスプロイトなし │
└──────────────────────────────────────────────────────────────────────────┘
$ cat ./design_decisions.mdfake_rpc_payload = b"\x05\x00\x0b\x03RpcAddPrinterDriverEx"
このペイロードは 25バイト で、2つの概念を同時に示しています:
バイト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))
なぜ135 (RPC Endpoint Mapper) ではなく445なのか?
PrintNightmare はRPC直接ではなく、SMB named pipe \pipe\spoolss をトランスポートとして使用します。実際のフローは以下の通りです:
1. TCP接続 → ポート445 (SMB)
2. SMBネゴシエーション + セッションセットアップ (NTLM/Kerberos認証)
3. Tree connect → IPC$
4. Named pipeオープン → \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
# spoolsv.exe がSYSTEMとして悪意のあるDLLを読み込む
# Windowsサービスのコード実行に相当
- T1055 # Process Injection
# spoolsv.exe (SYSTEM) プロセスのコンテキストにDLLが注入される
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 OR powershell.exe OR wscript.exe OR mshta.exe
重大度: 重大 — spoolsv はシェルを生成すべきではない
# 非標準パスから読み込まれた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 named pipeの監視: \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 — グループポリシーでリモート印刷をブロック
コンピューターの構成 → 管理用テンプレート → プリンター
→ 「Print Spoolerがクライアント接続を受け入れることを許可する」: 無効
これによりリモートベクターのみが無効化され、ローカル印刷は維持される
オプション3 — パッチを適用 (上記オプションに関わらず必須)
KB5004945 → 2021年7月の帯域外パッチ
+ その後の累積パッチ
パッチ適用後の検証 — レジストリにより依然として脆弱な場合がある:
REG QUERY "HKLM\Software\Policies\Microsoft\Windows NT\Printers\PointAndPrint"
NoWarningNoElevationOnInstall=1 または UpdatePromptSettings=0 の場合 → 依然として脆弱
修正: 両方の値を0に設定するか、キーを削除する
特別な優先事項: ドメインコントローラー
DCはデフォルトでPrint Spoolerを実行
PrintNightmare経由でDCを侵害 = 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[+] DCでデフォルト有効のPrint Spoolerが最も重大なシナリオ — DCでのSYSTEM = ゲームオーバー
[+] RPCトランスポートとしてのSMB named pipeは、境界重視の防御で過小評価されているベクター
[+] DCE/RPCは複雑なプロトコル — bind/call構造の理解がシグネチャ作成に役立つ
[+] CVE公開 ≠ パッチ適用 — パッチ後も数週間、ほとんどの環境は依然として脆弱だった
[+] PointAndPrintレジストリキーはパッチ適用後も脆弱性を再導入する可能性がある — パッチ後の管理が重要
[-] このPoCはTCP接続性のみを検証 — システムが実際にパッチ済みかどうかは検証しない
[-] SMBなしの純粋なソケットでは認証をネゴシエートできない — アプローチの根本的な制限
[-] settimeout(5) は低速ネットワークで誤検知を引き起こす可能性がある — パラメータ化可能なタイムアウトを検討
[→] 改善点: 実際のRPCにimpacketを使用、OSバージョンのフィンガープリント用に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月 (Patch Tuesday) | 2021年7月 (帯域外 KB5004945) |
| 脆弱な関数 | RpcAddPrinterDriverEx | RpcAddPrinterDriverEx |
| シナリオ | ローカル権限昇格 | SMB named pipe経由のリモートRCE |
| コンポーネント | このPoC | 実際のエクスプロイト |
|---|
| 接続 | ポート445へのTCPソケット | SMBセッション + Tree connect IPC$ |
| 認証 | なし | NTLMまたはKerberos (ドメインアカウント) |
| Named pipe | 未実装 | \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 |