
PowerShell 평가 스크립트로, 커널 버전, PKU2U 레지스트리 키, 노출된 SPNEGO 포트를 확인하여 Windows 시스템에서 CVE-2025-47981(SPNEGO NEGOEX 힙 오버플로)을 점검합니다. 수정 단계와 탐지 지침을 제공합니다.
유형: 취약점 평가 — 탐지 / 규정 준수 점검 CVE: CVE-2025-47981 CVSS: 9.8 Critical (AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H) CWE: CWE-122 — 힙 기반 버퍼 오버플로우 별칭: "SPNEGO Nightmare" / "Windows Authentication Wormable RCE" 패치: KB5062560 | 2025년 7월 Patch Tuesday
Windows 시스템이 CVE-2025-47981에 취약한지 확인하는 PowerShell 평가 스크립트 — SPNEGO Extended Negotiation (NEGOEX) 메커니즘의 힙 기반 버퍼 오버플로우로 인증 없이 RCE가 가능합니다. 익스플로잇을 실행하지 않음 — 노출 및 패치 상태만 평가합니다.
Developed by: HKK$ cat ./vulnerability_summary.txtCVE-2025-47981은 Windows SPNEGO 인증 메커니즘의 내부 확장 계층인 NEGOEX 프로토콜의 힙 기반 버퍼 오버플로우입니다. 이 취약점으로 인해 인증되지 않은 공격자가 원격으로 임의 코드를 실행하여 잠재적으로 시스템에 대한 완전한 제어권을 얻을 수 있습니다.
분석가들은 이미 이 CVE가 "심각한 문제가 될 불행한 특성"을 지니고 있으며, 사용자 상호작용 없이 취약한 시스템 간에 자동으로 확산될 수 있는 웜 가능성(wormable)이 있다고 설명했습니다.
이 취약점은 Windows 10(버전 1607 이상)과 Windows Server 2008 R2부터 Server 2025까지 모든 Windows Server(Server Core 변형 포함)에 영향을 미치며, x64, x86 및 ARM64 아키텍처에서 33개 이상의 서로 다른 Windows 및 Server 구성이 취약한 것으로 확인되었습니다.
$ cat ./technical_background.txtSPNEGO(Simple and Protected GSSAPI Negotiation Mechanism)는 Windows가 모든 인증 세션 전에 사용하는 인증 핸드셰이크 계층입니다. 애플리케이션은 프로토콜을 고정하지 않고 인증이 필요한 경우가 많습니다. Windows는 한 환경에서는 Kerberos를, 다른 환경에서는 NTLM을, 또는 다른 신뢰 모델에서는 확장 인증 메커니즘을 사용할 수 있습니다. SPNEGO는 사용할 인증 프로토콜을 결정하는 협상 메커니즘입니다.
클라이언트 서버
│ │
│──── SPNEGO Negotiation ────────►│
│ MechTypeList: │
│ [Kerberos, NTLM, NEGOEX] │
│ │
│◄─── Selected Mechanism ─────────│
│ │
│──── Auth Exchange ─────────────►│ ← 여기 NEGOEX에서 오버플로우 발생
NEGOEX는 SPNEGO 내부의 확장 메커니즘입니다 — PKU2U(피어 투 피어) 인증 및 기타 사용자 지정 메커니즘을 협상할 수 있게 합니다. 취약점은 여러 조각으로 전송된 과대 크기의 SPNEGO_TOKEN 구조를 처리하는 ntoskrnl!SpnegoHandleExtended 함수에 있으며, 커널 힙에서 오버플로우를 유발합니다.
"Network security: Allow PKU2U authentication requests to this computer to use online identities" 그룹 정책이 활성화된 시스템에서는 위험이 높습니다. 많은 Windows 배포에서 기본적으로 활성화되는 이 구성은 피어 투 피어 인증을 허용하여 NEGOEX의 취약한 코드 경로를 활성화함으로써, 그렇지 않으면 해당 경로를 노출하지 않을 엔드포인트에서 NEGOEX 공격 표면을 확장합니다.
$ cat ./architecture.txt┌─────────────────────────────────────────────────────────────────────────┐
│ CVE-2025-47981 ASSESSMENT SCRIPT — FLOW │
│ │
│ ┌──────────────────────────────────────────────────────────────────┐ │
│ │ CHECK 1: Windows Version │ │
│ │ Get-CimInstance Win32_OperatingSystem → .Version │ │
│ │ 컨텍스트: 패치 상관관계를 위한 정확한 빌드 식별 │ │
│ └──────────────────────────────────────────────────────────────────┘ │
│ │ │
│ ┌──────────────────────────────────────────────────────────────────┐ │
│ │ CHECK 2: ntoskrnl.exe Version │ │
│ │ Get-Item C:\Windows\System32\ntoskrnl.exe │ │
│ │ 비교: 설치 버전 < 10.0.14393.8246 → 취약 │ │
│ │ 비교: 설치 버전 ≥ 10.0.14393.8246 → KB5062560 적용됨 │ │
│ └──────────────────────────────────────────────────────────────────┘ │
│ │ │
│ ┌──────────────────────────────────────────────────────────────────┐ │
│ │ CHECK 3: PKU2U Registry Key │ │
│ │ HKLM:\SYSTEM\...\Lsa\pku2u\AllowOnlineID │ │
│ │ 1 → PKU2U 활성화 → 공격 표면 확장 │ │
│ │ 0 → PKU2U 비활성화 → PKU2U 벡터 완화됨 │ │
│ │ 없음 → 기본 구성 (GPO를 통해 평가) │ │
│ └──────────────────────────────────────────────────────────────────┘ │
│ │ │
│ ┌──────────────────────────────────────────────────────────────────┐ │
│ │ CHECK 4: 노출된 SPNEGO 포트 │ │
│ │ Get-NetTCPConnection → 135, 445, 5985, 3389, 80, 443, 25 │ │
│ │ 각 열린 포트 = 익스플로잇 전달 벡터 │ │
│ └──────────────────────────────────────────────────────────────────┘ │
│ │ │
│ Format-Table -AutoSize │
│ (펜테스트 보고서용 읽기 쉬운 출력) │
└─────────────────────────────────────────────────────────────────────────┘
$ cat ./design_decisions.mdntoskrnl.exe를 통한 버전 확인$kernelPath = [System.IO.Path]::Combine($env:SystemRoot, "System32\ntoskrnl.exe")
$requiredVersion = "10.0.14393.8246"
$installedVersion = (Get-Item $kernelPath).VersionInfo.FileVersion
if ([version]$installedVersion -lt [version]$requiredVersion) {
"취약 - 패치 누락 ($missingKB)"
}
왜 Get-HotFix가 아닌 ntoskrnl.exe인가?
Get-HotFix는 설치된 KB를 나열하지만 알려진 제한 사항이 있습니다:
DISM 또는 Windows Update를 통해 자동 모드로 적용된 KB를 감지하지 못함ntoskrnl.exe 버전을 직접 확인하는 것이 더 안정적입니다 — KB가 실제로 적용되고 시스템이 재부팅된 경우에만 파일이 패치된 버전을 받기 때문입니다. 재부팅이 보류된 KB가 있는 시스템은 여전히 메모리에 이전 커널 버전을 보유합니다.
[version] 캐스트: PowerShell은 기본적으로 문자열을 사전순으로 비교합니다 — "10.0.14393.8246" -lt "10.0.14393.800"은 $false(잘못됨)가 됩니다. [version]으로 캐스트하면 옥텟별 올바른 숫자 비교가 보장됩니다.
[System.IO.Path]::Combine($env:SystemRoot, ...): 하드코딩된 C:\Windows 대신 SystemRoot를 사용합니다 — Windows가 다른 드라이브에 설치된 시스템에서도 이식 가능합니다.
10.0.14393.824610.0.14393.xxxx → Windows 10 version 1607 / Windows Server 2016
│
└─ 8246 = KB5062560이 적용된 빌드
왜 이 특정 빌드인가?
Windows Server 2016(기본 빌드 14393)은 패치가 가장 중요한 환경 중 하나입니다 — DC, 파일 서버 및 기업 내부 서비스에서 널리 사용됩니다. 버전 8246은 KB5062560(2025년 7월) 적용 후의 커널 빌드에 해당합니다.
다른 운영 체제의 경우 요구되는 최소 빌드 번호가 다릅니다 — 스크립트는 OS별 버전 테이블로 확장할 수 있습니다.
AllowOnlineID$regPath = "HKLM:\SYSTEM\CurrentControlSet\Control\Lsa\pku2u"
$regName = "AllowOnlineID"
이 키는 무엇을 제어하나요?
이 취약점은 주로 "Allow PKU2U authentication requests to this computer to use online identities" 그룹 정책이 기본적으로 활성화된 시스템에 영향을 미치며, 이는 Windows 10 버전 1607 이상의 경우입니다.
AllowOnlineID 키는 해당 그룹 정책의 레지스트리 표현입니다. 활성화되면(= 1), 시스템은 PKU2U 인증을 수락합니다 — 오버플로우가 포함된 NEGOEX 코드 경로를 활성화합니다.
| 값 | 상태 | 위험 |
|---|---|---|
1 | PKU2U 활성화됨 | 높음 — NEGOEX 벡터 활성화됨 |
0 | PKU2U 비활성화됨 | 낮음 — 벡터 완화됨 (패치는 여전히 필요) |
| 없음 | 시스템 기본값 | GPO에 따라 다름 — gpresult /r로 확인 |
-ErrorAction SilentlyContinue: 키는 모든 시스템에 존재하지 않을 수 있습니다 — 스크립트는 오류를 생성하지 않고 부재를 정상적으로 처리합니다.
$ports = @(135, 445, 5985, 3389, 80, 443, 25)
공격자는 SPNEGO 인증을 사용하는 취약한 서비스(예: SMB(445/TCP), RDP(3389/TCP), HTTP/S(80, 443/TCP) 및 SMTP(25/TCP))에 악성 패킷을 보내 인증 없이 원격으로 이 결함을 악용할 수 있습니다.
| 포트 | 프로토콜 | SPNEGO가 사용되는 용도 |
|---|---|---|
135 | RPC Endpoint Mapper | RPC 인증 협상 |
445 | SMB | 파일 공유, named pipes 인증 |
5985 | WinRM (HTTP) | PowerShell 원격, 관리 |
3389 | RDP | 원격 데스크톱 인증 |
80 | HTTP | IIS Windows 인증 (Negotiate) |
443 | HTTPS | TLS를 통한 IIS Windows 인증 |
25 | SMTP | Exchange Extended Protection |
Get-NetTCPConnection -LocalPort $port는 로컬 시스템에서 포트가 LISTEN 상태인지 확인합니다 — 각 열린 포트는 익스플로잇을 위한 독립적인 전달 벡터를 나타냅니다.
$ cat ./mitre_mapping.yml# 공격자 관점 (스크립트가 탐지/방지하는 것)