垃圾洞,除了评分高一无是处
也是挺新的漏洞,依旧是5.12的patch才修好的。利用环境也是相当苛刻,效果也很有限制。
影响的版本只有Windows Server 系列(其实只要有ad服务,NetLogon就会启动,一眼只有server才装上)
注:尽管所有 Windows 版本均包含 netlogon.dll 文件,但该漏洞仅在配置为 Active Directory 域控制器的系统上才可被利用,因为 DC 定位器响应处理程序仅在此角色下处于活动状态。
我的复现版本
最终效果是让 LSASS 崩溃
环境搭建
复现这个漏洞最重要的就是搭建环境 ,之前写过一个版本的复现全是踩坑。
https://gist.github.com/exolocity/aa6d7c097a5c8658f8914f9f90513181
vmware搭建的时候记得选桌面版的,不然只有cmd
第一个重要的点:计算机名要足够长 ,例如:3f4c5a2d-1b6e-4f2a-9c8d-7e5a1b3c9d0e
然后开始安装域控,就是正常的安装流程
第二个重要点:配置域名要足够长,并对应的NetBIOS名字也要尽量长 ,例如:CCCCDDDDdeptdivisionengineeringenterprisecorporati.o.n.l.o.c.a.l
这里最好填满15个字符
PoC调试
说实话环境不对的话,网上的所有PoC没有一个打的通
静态分析
根据公开的研究资料[3],调用路径如下(这个倒是不难逆向出来)
ntdsai!LDAP_CONN::SearchRequest -> ntdsai!LDAP_GetRootDSEAttNetlogon -> netlogon!I_NetLogonLdapLookupEx -> netlogon!NlGetLocalPingResponse -> netlogon!LogonRequestHandler -> netlogon!BuildSamLogonResponse -> netlogon!NetpLogonPutUnicodeString (x3, no bounds check) -> netlogon!NlpUtf8ToCutf8 (x3, DNS names overflow past buffer end)
大致意思是说在netlogon!NetpLogonPutUnicodeString完成查询用户名的复制,最后在netlogon!NlpUtf8ToCutf8完成组装,组装的时候发生栈溢出。可以参考[4]进行LSASS的调试
NetpLogonPutUnicodeString做的就是复制数据
在BuildSamLogonResponse接受了这几个复制
具体意思是
NetpLogonPutUnicodeString(src, size, dst)
然后每次让v26向后移动size大小,最后溢出的位置也是这里。Src大小是568的char,这里要占有2+36+0x82+32=398字节大小(因为是wchar)
然后调用NlpUtf8ToCutf8进行拼接
NlpUtf8ToCutf8根据参数复制到Src变量中,整理一下写入的代码
n122 = NlpUtf8ToCutf8(Src, NlGlobalUtf8DnsForestName, 0 , &v26, &n260, &n3, v34, &v32); n122 = NlpUtf8ToCutf8(Src, v19, 0 , &v26, &n260, &n3, v34, &v32); if ( n3 >= 3 || (n122 = NlpUtf8ToCutf8(Src, DnsDomain[36 ], 0 , &v26, &n260, &n3, v34, &v32)) == 0 )
整理得到复制的顺序和大小
+2 : optNum +74+2 : server name +262+74+2 : query name // 可以被我们控制 +66+262+74+2 : domain name +16+66+262+74+2 : some GUID 1 +16+16+66+262+74+2 : some GUID 2 +15+16+16+66+262+74+2 : 林名称 +64+15+16+16+66+262+74+2 : 域名称 +36+64+15+16+16+66+262+74+2 : 主机名称 +16+36+64+15+16+16+66+262+74+2 : 运行时环境
如果可行的话最长长度已经是567了
注意: +66+262+74+2 : domain name,这里也强调了为什么,之前设置的NetBIOS Domain Name一定要长!如果这里果断地话吃不到处理WCHAR引起的x2字节复制的“增益”
追踪变量发现来自NlGetLocalPingResponse
最后的溢出是存在于这里。最后开启日志
nltest /dbflag:0x2080ffff powershell Get-Content C:\Windows\debug\netlogon.log -Wait // 可以实时查看日志内容
动态调试
poc来源[2]:https://github.com/0xABCD01/CVE-2026-41089
2: kd> .prompt_allow +reg +ea +dis Allow the following information to be displayed at the prompt: (Other settings can affect whether the information is actually displayed) sym - Symbol for current instruction dis - Disassembly of current instruction ea - Effective address for current instruction reg - Register state src - Source info for current instruction Do not allow the following information to be displayed at the prompt: None 2: kd> !process 0 0 lsass.exe PROCESS ffffc2881a0740c0 SessionId: 0 Cid: 02d8 Peb: 72d4be9000 ParentCid: 0234 DirBase: 11320b000 ObjectTable: ffffad034242c000 HandleCount: 2321. Image: lsass.exe 2: kd> .process /i ffffc2881a0740c0;g You need to continue execution (press 'g' <enter>) for the context to be switched. When the debugger breaks in again, you will be in the new process context. Break instruction exception - code 80000003 (first chance) rax=0000000000000000 rbx=00000000000000bd rcx=0000000000000007 rdx=ffffc288172b2040 rsi=0000000000000000 rdi=ffffc2881a0740c0 rip=fffff8005de1edc0 rsp=ffff94877f3322c8 rbp=ffff94877f332340 r8=ffffc2881731d128 r9=7ffff8005e747400 r10=ffffffffffffffff r11=0000000000000000 r12=0000000000000000 r13=0000000000000000 r14=ffffc2881a0740c0 r15=0000000000000000 iopl=0 nv up ei ng nz na pe nc cs=0010 ss=0018 ds=002b es=002b fs=0053 gs=002b efl=00040286 nt!DbgBreakPointWithStatus: fffff800`5de1edc0 cc int 3 0: kd> .reload /f /user //刷新kd维护的用户态加载模块列表使之匹配当前进程,这一步有些耗时,耐心等待
下个BuildSamLogonResponse断点
0: kd> dt nt!_EPROCESS UniqueProcessId ImageFileName @$proc +0x440 UniqueProcessId : 0x00000000`000002d8 Void +0x5a8 ImageFileName : [15] "lsass.exe" 0: kd> bp /p @$proc netlogon!BuildSamLogonResponse
查看日志发现PoC[2]没有打通,但是观察日志文件 C:\Windows\debug\netlogon.log
发现最后走到的是BuildSamLogonResponseEx而非BuildSamLogonResponse。并且发现问题:NetpLogonPutUnicodeString的复制函数只有BuildSamLogonResponse在使用
下断点看看调用栈
0: kd> k # Child-SP RetAddr Call Site 00 0000003f`c367daa8 00007ff8`d98f5a6b netlogon!BuildSamLogonResponseEx 01 0000003f`c367dab0 00007ff8`d98f6db6 netlogon!LogonRequestHandler+0x417 02 0000003f`c367dbe0 00007ff8`d9925163 netlogon!NlGetLocalPingResponse+0x4c2 03 0000003f`c367df20 00007ff8`d862e28d netlogon!I_NetLogonLdapLookupEx+0x503 04 0000003f`c367e410 00007ff8`d856a174 ntdsai!LDAP_GetRootDSEAttNetlogon+0x7d 05 0000003f`c367e4c0 00007ff8`d8545f84 ntdsai!LDAP_GetDSEAtts+0x4f8 06 0000003f`c367e730 00007ff8`d88b4c57 ntdsai!LDAP_CONN::SearchRequest+0x78c 07 0000003f`c367ef50 00007ff8`d85174b4 ntdsai!LDAP_CONN::SearchRequest+0x73 08 0000003f`c367efd0 00007ff8`d84fb5d4 ntdsai!LDAP_CONN::ProcessRequestEx+0x3014 09 0000003f`c367f3b0 00007ff8`d858d6c1 ntdsai!LDAP_CONN::IoCompletion+0xa28 0a 0000003f`c367f720 00007ff8`d85c018b ntdsai!ProcessNewClient+0x11d 0b 0000003f`c367f7d0 00007ff8`d84b3c69 ntdsai!UDPIoCompletion+0x19b 0c 0000003f`c367fd90 00007ff8`d84b392d NTDSATQ!AtqpProcessContext+0xf9 0d 0000003f`c367fde0 00007ff8`dbb34ed0 NTDSATQ!AtqPoolThread+0x22d 0e 0000003f`c367fe90 00007ff8`dd0ce39b KERNEL32!BaseThreadInitThunk+0x10 0f 0000003f`c367fec0 00000000`00000000 ntdll!RtlUserThreadStart+0x2b
v19的值是esi,根据条件发现v19<4才能走到else。看看寄存器明显不符合
0: kd> r rax=0000000000000000 rbx=0000000000000000 rcx=000001ace3e88500 rdx=0000000000000000 rsi=0000000000000016 rdi=0000000000000015 rip=00007ff8d98f4d18 rsp=0000003fc367daa8 rbp=0000003fc367db91 r8=0000000000000015 r9=0000003fc367e0b0 r10=0000000000000000 r11=0000003fc367da80 r12=0000000000000010 r13=0000003fc367e0b0 r14=0000000000000002 r15=000001ace3e88500 iopl=0 nv up ei pl nz na po nc cs=0033 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00000202 netlogon!BuildSamLogonResponseEx: 0033:00007ff8`d98f4d18 48895c2410 mov qword ptr [rsp+10h],rbx ss:002b:0000003f`c367dab8=0000000000000016
在LogonRequestHandler下断点看看a6长啥样
0: kd> dq @rbp+77 L1 0000003f`c2f7d8a8 0000003f`00000016 0: kd> k # Child-SP RetAddr Call Site 00 0000003f`c2f7d748 00007ff8`d98f5a6b netlogon!BuildSamLogonResponseEx 01 0000003f`c2f7d750 00007ff8`d98f6db6 netlogon!LogonRequestHandler+0x417 02 0000003f`c2f7d880 00007ff8`d9925163 netlogon!NlGetLocalPingResponse+0x4c2 0: kd> dd CA04C+netlogon L1 00007ff8`d999a04c 00000000
这里结果为0,跳过if,那么后面就不应该有对v19的修改了。继续返回调用栈查看,发现依旧是参数,说明也需要指定某一种东西。
这里又要才一个坑,首先是为了通过刚才这段猜测需要重新修改PoC中build_cldap_ping的ntver=0x00000002,为什么是2,因为是其他值会通不过如下判断:
最后去真正溢出发生的地方NlGetLocalPingResponse+4C2:
同时发现rbp+0x40有一个值
溢出应该会覆盖这个值从而破坏canary保护
利用评估
几乎无法利用
即使溢出存在,但是溢出的数据并不受我们控制,构造有效payload可能需要借助其他漏洞
因为存在canary保护,且溢出空间有限,怀疑无法使用栈溢出构建SEH链执行shellcode
大部分域名配置都不会有这么长吧,受害面积较小
但是任然可以当作DOS洞恶心一下对面 \doge
参考
[1] Windows Netlogon Remote Code Execution Vulnerability https://msrc.microsoft.com/update-guide/vulnerability/CVE-2026-41089
[2] 0xABCD01/CVE-2026-41089 https://github.com/0xABCD01/CVE-2026-41089
[3] CVE-2026-41089 — Microsoft Windows Netlogon BuildSamLogonResponse Stack-based Buffer Overflow RCE https://aretiq.ai/research/vul260513-cve-2026-41089-microsoft-windows-netlogon-buildsamlogonresponse-stack-based-buffer-overflow-rce/
[4] Windows安全入门技能–调试lsass https://blog.nsfocus.net/windows-lsass/