
PowerShell-скрипт для оценки, который проверяет системы Windows на наличие CVE-2025-47981 (переполнение кучи SPNEGO NEGOEX) путем проверки версии ядра, ключа реестра PKU2U и открытых портов SPNEGO. Предоставляет шаги по устранению уязвимости и рекомендации по обнаружению.
Тип: Оценка уязвимости — Обнаружение / Проверка соответствия 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 | July 2025 Patch Tuesday
Скрипт PowerShell для оценки, который проверяет, уязвима ли система Windows к CVE-2025-47981 — переполнение буфера в куче в механизме SPNEGO Extended Negotiation (NEGOEX), которое позволяет выполнить RCE без аутентификации. Не выполняет эксплойт — только оценивает подверженность и состояние патча.
Разработано: HKK$ cat ./vulnerability_summary.txtCVE-2025-47981 — это переполнение буфера в куче в протоколе NEGOEX — внутреннем слое расширения механизма аутентификации SPNEGO в Windows. Уязвимость позволяет неаутентифицированным злоумышленникам выполнять произвольный удаленный код, потенциально получая полный контроль над системой.
Аналитики уже описали CVE как имеющую "несчастливые характеристики превращения в значительную проблему", с потенциалом wormable — способностью автоматически распространяться между уязвимыми системами без взаимодействия с пользователем.
Уязвимость затрагивает Windows 10 (начиная с версии 1607) и все Windows Server с 2008 R2 до Server 2025, включая варианты Server Core — более 33 различных конфигураций Windows и Server подтверждены как уязвимые на архитектурах x64, x86 и ARM64.
$ 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 (peer-to-peer) и другие настраиваемые механизмы. Уязвимость находится в функции ntoskrnl!SpnegoHandleExtended, которая обрабатывает структуры SPNEGO_TOKEN увеличенного размера, отправляемые несколькими фрагментами, вызывая переполнение в куче ядра.
Риск повышен в системах, где групповая политика "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)"
}
Почему ntoskrnl.exe, а не Get-HotFix?
Get-HotFix перечисляет установленные KB, но имеет известные ограничения:
DISM или Windows Update в тихом режимеПроверка версии ntoskrnl.exe напрямую более надежна — файл получает пропатченную версию только когда KB был фактически применен и система перезагружена. Система с KB, ожидающим перезагрузки, все еще будет иметь старую версию ядра в памяти.
Приведение [version]: PowerShell по умолчанию сравнивает строки лексикографически — "10.0.14393.8246" -lt "10.0.14393.800" было бы $false (неправильно). Приведение к [version] гарантирует корректное числовое сравнение по октетам.
[System.IO.Path]::Combine($env:SystemRoot, ...): использует SystemRoot вместо жестко заданного C:\Windows — переносимо для систем с 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).
Для других операционных систем требуемый минимальный номер сборки отличается — скрипт может быть расширен таблицей версий для каждой ОС.
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)
Злоумышленники могут эксплуатировать уязвимость удаленно без аутентификации, отправляя вредоносные пакеты на уязвимые службы, такие как SMB (порт 445/TCP), RDP (порт 3389/TCP), HTTP/S (порты 80, 443/TCP) и SMTP (порт 25/TCP), которые используют аутентификацию SPNEGO.
| Порт | Протокол | SPNEGO используется для |
|---|---|---|
135 | RPC Endpoint Mapper | Согласование аутентификации RPC |
445 | SMB | Аутентификация файловых ресурсов, именованных каналов |
5985 | WinRM (HTTP) | Удаленное управление PowerShell |
3389 | RDP | Аутентификация Remote Desktop |
80 | HTTP | Windows Authentication IIS (Negotiate) |
443 | HTTPS | Windows Authentication IIS через TLS |
25 | SMTP | Exchange Extended Protection |
Get-NetTCPConnection -LocalPort $port проверяет, находится ли порт в состоянии LISTEN в локальной системе — каждый открытый порт представляет независимый вектор доставки для эксплойта.
$ cat ./mitre_mapping.yml# Перспектива АТАКУЮЩЕГО (что скрипт обнаруживает/предотвращает)
tactic: Initial Access
- T1190 # Exploit Public-Facing Application
# RCE через переполнение кучи SPNEGO без аутентификации
# Вектор: любой порт с Negotiate auth (445, 5985, 3389...)
tactic: Execution
- T1203 # Exploitation for Client Execution
# Переполнение кучи в ntoskrnl!SpnegoHandleExtended
# Контроль RIP/EIP через повреждение кучи ядра
tactic: Lateral Movement
- T1210 # Exploitation of Remote Services
# Wormable: эксплуатирует другие хосты через SMB/RPC без учетных данных
- T1550.002 # Pass-the-Hash
# После RCE: доступ SYSTEM позволяет извлечение хэшей LSASS
tactic: Privilege Escalation
- T1068 # Exploitation for Privilege Escalation
# Переполнение буфера в контексте ядра → немедленный ring 0
# Перспектива ЗАЩИТНИКА (что выполняет скрипт оценки)
tactic: Discovery (Blue Team)
- T1082 # System Information Discovery
# Сбор версии ОС и ntoskrnl.exe для оценки патча
- T1012 # Query Registry
# Проверка HKLM:\...\pku2u\AllowOnlineID
- T1049 # System Network Connections Discovery
# Get-NetTCPConnection для картирования открытых портов SPNEGO
$ cat ./detection_opportunities.md# Аномалия аутентификации NEGOEX — пакеты SPNEGO увеличенного размера
# Источник: Windows Security Event Log / ETW
EventID: 4625 (Logon Failure) с SubStatus 0xC000006D
+ Источник: внешние хосты
+ Частота: высокая (попытки сканирования/эксплойта)
+ TargetUserName: ANONYMOUS LOGON ИЛИ пусто
# Альтернатива: Sysmon Event 3 (Network Connection)
EventID: 3
Условие:
DestinationPort: 445 ИЛИ 5985 ИЛИ 135
Initiated: false (входящее соединение)
Image: System ИЛИ lsass.exe
# Сбой ядра после неудачного эксплойта
# Источник: Windows Event Log → System
EventID: 1001 (BugCheck)
BugCheckCode: 0x00000050 (PAGE_FAULT_IN_NONPAGED_AREA)
ИЛИ
BugCheckCode: 0x0000007E (SYSTEM_THREAD_EXCEPTION_NOT_HANDLED)
Контекст: Сбой в ntoskrnl.exe → возможная попытка эксплойта
# Snort/Suricata — токен SPNEGO увеличенного размера (концептуально)
alert tcp any any -> $HOME_NET [445,5985,3389] (
msg:"CVE-2025-47981 SPNEGO NEGOEX oversized token";
content:"|60|"; # SPNEGO OID marker
content:"|a0|"; # MechTypeList marker
dsize:>4096; # легитимные токены редко превышают 4KB
threshold:type both, track by_src, count 3, seconds 10;
sid:2025479810;
)
$ cat ./remediation.mdПРИОРИТЕТ: КРИТИЧЕСКИЙ — Немедленный патч (CVSS 9.8, wormable)
1. ПАТЧ (основное действие):
Windows Update → KB5062560 (July 2025 Patch Tuesday)
WSUS: утвердить KB5062560 для всех систем Windows 10 1607+
ПЕРЕЗАГРУЗИТЬ после патча — ntoskrnl.exe заменяется только после перезагрузки
2. ПРОВЕРКА ПОСЛЕ ПАТЧА:
Запустить этот скрипт снова
Ожидаемый результат:
ntoskrnl.exe Installed Version: 10.0.14393.8246 (или выше)
Vulnerability Result: Безопасно - Патч применен
3. ВРЕМЕННОЕ СМЯГЧЕНИЕ (если немедленный патч невозможен):
Отключить PKU2U через групповую политику:
Computer Configuration → Windows Settings → Security Settings →
Local Policies → Security Options →
"Network security: Allow PKU2U authentication requests..." → DISABLED
ИЛИ через реестр:
Set-ItemProperty "HKLM:\SYSTEM\CurrentControlSet\Control\Lsa\pku2u"
-Name AllowOnlineID -Value 0
4. СЕТЕВАЯ БЛОКИРОВКА (защита в глубину):
Межсетевой экран: ограничить входящие 135, 445, 5985 авторизованными хостами
Сегментировать DC и критически важные серверы в VLAN с жесткими ACL
5. ОСОБЫЙ ПРИОРИТЕТ — Domain Controllers:
DC открывают все перечисленные порты (RPC, SMB, LDAP)
Wormable + скомпрометированный DC = полная компрометация домена AD
Патчить DC в первом доступном окне
$ cat ./usage.sh# Запустить скрипт оценки (не требует прав администратора для базового чтения,
# но некоторые проверки реестра могут потребовать повышения прав)
powershell.exe -ExecutionPolicy Bypass -File cve_2025_47981_check.ps1
# Ожидаемый вывод на УЯЗВИМОЙ системе:
Name Value
---- -----
ntoskrnl.exe Installed Version 10.0.14393.7906
ntoskrnl.exe Required Version 10.0.14393.8246
PKU2U AllowOnlineID 1
Открытые порты SPNEGO {135, 445, 5985, 3389}
Vulnerability Result Уязвим - Патч отсутствует (KB5062560)
Windows Version 10.0.14393.7906
# Ожидаемый вывод на ПРОПАТЧЕННОЙ системе:
Vulnerability Result Безопасно - Патч применен
PKU2U AllowOnlineID 0
$ cat ./affected_versions.txtЗАТРОНУТЫ (33+ конфигурации):
Windows 10: 1607, 1809, 21H2, 22H2
Windows 11: 22H2, 23H2, 24H2
Windows Server: 2008 R2, 2012, 2012 R2, 2016, 2019, 2022, 2025
Архитектуры: x64, x86, ARM64
Server Core: Да (все вышеперечисленные версии)
ПОВЫШЕННЫЙ ФАКТОР РИСКА:
PKU2U GPO включена (по умолчанию в Win10 1607+)
Порты 135/445/5985 доступны из внешних или недоверенных сетей
ПАТЧ:
KB5062560 → July 2025 Patch Tuesday
Минимальный ntoskrnl.exe → 10.0.14393.8246 (Windows Server 2016)
Проверить конкретные сборки для каждой версии: msrc.microsoft.com
$ cat ./lessons_learned.txt[+] Сравнение [version] вместо строки предотвращает ложные отрицательные результаты в сравнениях сборок
[+] ntoskrnl.exe — основной источник истины для состояния патча — надежнее, чем Get-HotFix
[+] PKU2U AllowOnlineID — усилитель риска — системы без него имеют уменьшенную поверхность
[+] Get-NetTCPConnection быстро картирует локально открытую поверхность атаки
[+] Format-Table -AutoSize генерирует вывод, готовый для копирования в отчет по пентесту
[-] Скрипт проверяет только Windows Server 2016 (14393) — необходимо расширение для других сборок
[-] Не проверяет состояние GPO через gpresult — реестр может расходиться с действующей политикой
[-] Не тестирует удаленное подключение — только проверяет, открыты ли порты локально
[-] Нет вывода в JSON/CSV — сложно интегрировать в автоматизированные конвейеры соответствия
[→] Улучшения: таблица версий для каждой ОС, вывод в JSON, удаленная проверка через Invoke-Command,
интеграция с Qualys/Tenable для корреляции уязвимостей
CVE Assessment · CVSS 9.8 · Wormable · July 2025 Patch Tuesday · Detection only · No exploit