垃圾洞,除了评分高一无是处

也是挺新的漏洞,依旧是5.12的patch才修好的。利用环境也是相当苛刻,效果也很有限制。

image-20260602203409710

影响的版本只有Windows Server 系列(其实只要有ad服务,NetLogon就会启动,一眼只有server才装上)

注:尽管所有 Windows 版本均包含 netlogon.dll 文件,但该漏洞仅在配置为 Active Directory 域控制器的系统上才可被利用,因为 DC 定位器响应处理程序仅在此角色下处于活动状态。

image-20260602205501214

我的复现版本

image-20260603154859640

最终效果是让 LSASS 崩溃

image-20260605174713717

环境搭建

复现这个漏洞最重要的就是搭建环境,之前写过一个版本的复现全是踩坑。

image-20260605174039700

https://gist.github.com/exolocity/aa6d7c097a5c8658f8914f9f90513181

vmware搭建的时候记得选桌面版的,不然只有cmd

第一个重要的点:计算机名要足够长,例如:3f4c5a2d-1b6e-4f2a-9c8d-7e5a1b3c9d0e

image-20260605170613091

然后开始安装域控,就是正常的安装流程

image-20260605170752621

image-20260605170807834

第二个重要点:配置域名要足够长,并对应的NetBIOS名字也要尽量长,例如:CCCCDDDDdeptdivisionengineeringenterprisecorporati.o.n.l.o.c.a.l

image-20260605170917243

这里最好填满15个字符

image-20260605171047677

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做的就是复制数据

image-20260603194539215

BuildSamLogonResponse接受了这几个复制

image-20260605130129700

具体意思是

NetpLogonPutUnicodeString(src, size, dst)

然后每次让v26向后移动size大小,最后溢出的位置也是这里。Src大小是568的char,这里要占有2+36+0x82+32=398字节大小(因为是wchar)

image-20260605130439736

然后调用NlpUtf8ToCutf8进行拼接

image-20260603195140980

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

image-20260603195419185

最后的溢出是存在于这里。最后开启日志

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

image-20260603200016199

发现最后走到的是BuildSamLogonResponseEx而非BuildSamLogonResponse。并且发现问题:NetpLogonPutUnicodeString的复制函数只有BuildSamLogonResponse在使用

image-20260603200208356

下断点看看调用栈

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

image-20260604202021310

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

image-20260604202224794

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

image-20260604203115924

这里结果为0,跳过if,那么后面就不应该有对v19的修改了。继续返回调用栈查看,发现依旧是参数,说明也需要指定某一种东西。

image-20260604203605088

image-20260605171524474

这里又要才一个坑,首先是为了通过刚才这段猜测需要重新修改PoC中build_cldap_pingntver=0x00000002,为什么是2,因为是其他值会通不过如下判断:

image-20260604214002449

image-20260604213950400

最后去真正溢出发生的地方NlGetLocalPingResponse+4C2

image-20260605172802146

同时发现rbp+0x40有一个值

image-20260605135003039

image-20260605135123434

溢出应该会覆盖这个值从而破坏canary保护

image-20260605173536467

image-20260605174713717

image-20260605174725490

利用评估

几乎无法利用

  1. 即使溢出存在,但是溢出的数据并不受我们控制,构造有效payload可能需要借助其他漏洞
  2. 因为存在canary保护,且溢出空间有限,怀疑无法使用栈溢出构建SEH链执行shellcode
  3. 大部分域名配置都不会有这么长吧,受害面积较小

但是任然可以当作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/