ABUSING .NET CORE CLR DIAGNOSTIC FEATURES (+ CVE-2023-33127)

INTRODUCTION 介绍

BACKGROUND 背景

.NET is an ecosystem of frameworks, runtimes, and languages for building and running a wide range of applications on a variety of platforms and devices. The .NET Framework was initially released in the early 2000s as Microsoft’s implementation of the Common Language Infrastructure (CLI) specification. In 2016, Microsoft released .NET Core, the first truly open-source, cross platform version of the .NET Platform.
.NET 是一个由框架、运行时和语言组成的生态系统,用于在各种平台和设备上生成和运行各种应用程序。.NET Framework 最初于 2000 年代初发布,作为 Microsoft 对公共语言基础结构 (CLI) 规范的实现。2016 年,Microsoft 发布了 .NET Core,这是 .NET 平台的第一个真正开源的跨平台版本。

All flavors of .NET rely on a runtime component called the Common Language Runtime (CLR). The CLR is responsible for executing managed programs (e.g. assemblies) and handling other tasks such as memory management, garbage collection, and just-in-time (JIT) compilation of manage-to-unmanaged code. In open-source .NET, the CLR is implemented as the Core CLR (e.g. coreclr.dll).
所有版本的 .NET 都依赖于称为公共语言运行时 (CLR) 的运行时组件。CLR 负责执行托管程序(例如程序集)并处理其他任务,例如内存管理、垃圾回收和管理到非托管代码的实时 (JIT) 编译。在开源 .NET 中,CLR 作为核心 CLR(例如 coreclr.dll)实现。

Although the .NET Framework will be referenced frequently, this blog will focus on abusing several runtime diagnostic features that are mostly specific to open-source .NET on modern Microsoft Windows client operating systems (e.g. .NET, formerly called .NET Core, since version 5).
尽管 .NET Framework 将经常被引用,但本博客将重点介绍滥用几个运行时诊断功能,这些功能主要特定于现代 Microsoft Windows 客户端操作系统(例如 .NET,以前称为 .NET Core,自版本 5 起)上的开源 .NET。

Of note, the content provided in this blog was first presented in my MCTTP 2023 Conference talk – Dotnet: Not Dead…Yet. Defensive considerations, SIGMA rules, and mitigation guidance are located at the end of the post.
值得注意的是,本博客中提供的内容首次出现在我的 MCTTP 2023 会议演讲中——Dotnet:Not Dead…还。防御注意事项、SIGMA 规则和缓解指南位于文章末尾。

.NET NATIVE INCLUSION .NET 本机包含

Although it may be a surprise to a few, .NET Framework (4.8.x) is still the default “system wide” .NET implementation on Microsoft Windows. However, Windows ships with several Universal Windows Platform (UWP) applications (“apps”) that rely on .NET Native, a .NET pre-compilation technology that contains an instance of the Core CLR runtime. An example UWP app that leverages .NET Native is the Phone Link app (PhoneExperienceHost.exe).
尽管可能会让一些人感到惊讶,但 .NET Framework (4.8.x) 仍然是 Microsoft Windows 上默认的“系统范围”.NET 实现。但是,Windows 附带了多个通用 Windows 平台 (UWP) 应用程序(“应用”),这些应用程序依赖于 .NET Native,这是一种包含核心 CLR 运行时实例的 .NET 预编译技术。利用 .NET Native 的 UWP 应用示例是电话链接应用 (PhoneExperienceHost.exe)。

ABUSING .NET CORE CLR DIAGNOSTIC FEATURES (+ CVE-2023-33127)

Note: Visual Studio components and Azure DevOps Pipeline Agents leverage the open-source .NET runtime. Most recently, .NET version 8 was released.
注意:Visual Studio 组件和 Azure DevOps 管道代理利用开源 .NET 运行时。最近,发布了 .NET 版本 8。

RUNTIME CONFIGURATION & DIAGNOSTICS
运行时配置和诊断

Over the last few years, I’ve blogged about several ways to abuse the .NET Framework by leveraging CLR Configuration Knobs. Adjusting knobs allow for controlling the behavior of the .NET Common Language Runtime (CLR) for development, debugging, and diagnostic purposes. The Core CLR is no exception and includes many similar and unique knobs that can be configured in the registry, environment variables, and configuration files.
在过去的几年中,我在博客中介绍了利用 CLR 配置旋钮滥用 .NET Framework 的几种方法。通过调整旋钮,可以控制 .NET 公共语言运行时 (CLR) 的行为,以便进行开发、调试和诊断。Core CLR 也不例外,它包含许多类似且独特的旋钮,可以在注册表、环境变量和配置文件中配置。

A very interesting and well supported diagnostic extension for the .NET Framework CLR is the profiling API. As stated by Microsoft, a profiler is a “tool that monitors the execution of another application. [It] is a dynamic link library (DLL) that consists of functions that receive messages from, and send messages to, the CLR by using the profiling API. The profiler DLL is loaded by the CLR at run time.” Messaging to and from the profiler DLL and the CLR are implemented through the ICorProfilerCallback/2 interface for event notification and the ICorProfilerInfo/2 interface for profiled application state information. Profiling a .NET application could reveal event(ing) information such as assembly loading, module loading, and thread creation (Source: Microsoft Docs).
.NET Framework CLR 的一个非常有趣且受良好支持的诊断扩展是分析 API。正如Microsoft所说,分析器是“监视另一个应用程序执行的工具。[It] 是一个动态链接库 (DLL),它由使用分析 API 从 CLR 接收消息和向 CLR 发送消息的函数组成。探查器 DLL 由 CLR 在运行时加载。通过用于事件通知的 ICorProfilerCallback /2 接口和用于分析的应用程序状态信息的 ICorProfilerInfo/2 接口实现与探查器 DLL 和 CLR 之间的消息传递。分析 .NET 应用程序可能会显示事件信息,例如程序集加载、模块加载和线程创建(来源:Microsoft Docs)。

Interestingly, open-source .NET includes a rich set of troubleshooting diagnostic features, tools, and APIs that can be leveraged to interface with the Core CLR without the need of a profiler, though profiling is also supported (which we’ll dive into shortly). Of note, Microsoft documentation for Core runtime diagnostics is very robust and well worth reviewing.
有趣的是,开源 .NET 包含一组丰富的故障排除诊断功能、工具和 API,可用于与核心 CLR 交互,而无需探查器,但也支持分析(我们稍后将深入探讨)。值得注意的是,核心运行时诊断的 Microsoft 文档非常可靠,非常值得查看。

CLR PROFILER ABUSE CLR 探查器滥用

.NET FRAMEWORK CLR PROFILER LOADING
.NET FRAMEWORK CLR 探查器加载

At .NET application start, configuration knobs adjust the CLR/runtime behavior. As documented by Casey Smith (@subTee) in 2017, the following .NET Framework profiler knobs are configured as environment variables to load an unmanaged “profiler” DLL:
在 .NET 应用程序启动时,配置旋钮会调整 CLR/运行时行为。正如 Casey Smith (@subTee) 在 2017 年所记录的那样,以下 .NET Framework 探查器旋钮配置为环境变量,以加载非托管的“探查器”DLL:

  • COR_ENABLE_PROFILING – Set to 1 to enable profiler loading
    COR_ENABLE_PROFILING – 设置为 1 以启用探查器加载
  • COR_PROFILER – Set a target CLSID or arbitrary GUID value (Note: Not necessarily required for the .NET Framework)
    COR_PROFILER – 设置目标 CLSID 或任意 GUID 值(注意:.NET Framework 不一定需要)
  • COR_PROFILER_PATH – Set path to the profiler DLL
    COR_PROFILER_PATH – 设置探查器 DLL 的路径

If an arbitrary DLL is loaded into the CLR that does not meet the requirements and structure for a profiler DLL, the CLR will effectively unload the library. Depending on the offensive use case, this may or may not be important. Additionally, this technique is documented in Mitre ATT&CK as sub-technique: T1574.012.
如果将任意 DLL 加载到不符合探查器 DLL 的要求和结构的 CLR 中,则 CLR 将有效地卸载该库。根据攻击性用例,这可能重要也可能不重要。此外,该技术在 Mitre ATT&CK 中记录为子技术:T1574.012。

.NET CORE CLR PROFILER LOADING
.NET CORE CLR 探查器加载

The Core CLR profiler in open-source .NET acts in a similar way but leverages the following knobs to load a “profiler” DLL:
开源 .NET 中的核心 CLR 探查器以类似的方式运行,但利用以下旋钮加载“探查器”DLL:

  • CORECLR_ENABLE_PROFILING – Set to 1 to enable profiler loading
    CORECLR_ENABLE_PROFILING – 设置为 1 以启用探查器加载
  • CORECLR_PROFILER – Set an arbitrary GUID value (Note: Required for open-source .NET)
    CORECLR_PROFILER – 设置任意 GUID 值(注意:对于开源 .NET 是必需的)
  • CORECLR_PROFILER_PATH – Set path to the profiler DLL (Note: knob names may also be CORECLR_PROFILER_PATH_32 or CORECLR_PROFILER_PATH_64 depending on architecture)
    CORECLR_PROFILER_PATH – 设置探查器 DLL 的路径(注意:旋钮名称也可能是CORECLR_PROFILER_PATH_32或CORECLR_PROFILER_PATH_64,具体取决于体系结构)

When set as environment variables in the registry, the .NET application Core CLR loads the DLL for execution and persistence:
在注册表中设置为环境变量时,.NET 应用程序 Core CLR 将加载 DLL 以进行执行和持久性:

ABUSING .NET CORE CLR DIAGNOSTIC FEATURES (+ CVE-2023-33127)

.NET CORE CLR DIAGNOSTICS
.NET CORE CLR 诊断.NET CORE CLR DIAGNOSTICS

CLR DIAGNOSTIC PORT CLR 诊断端口

As mentioned prior, the .NET Core CLR diagnostic analysis can be performed without the use of a CLR profiler. By default, the Core CLR enables an Interprocess Communication (IPC) diagnostic endpoint called a diagnostic port. On Linux and MAC, the IPC occurs over Unix domain sockets by default. On Windows, IPC occurs over a named pipe, which follows this naming convention:
如前所述,可以在不使用 CLR 探查器的情况下执行 .NET Core CLR 诊断分析。默认情况下,核心 CLR 启用称为诊断端口的进程间通信 (IPC) 诊断终结点。在 Linux 和 MAC 上,默认情况下,IPC 发生在 Unix 域套接字上。在 Windows 上,IPC 发生在命名管道上,该管道遵循以下命名约定:

\.\pipe\dotnet-diagnostic-{Process ID (PID) of .NET application}
ABUSING .NET CORE CLR DIAGNOSTIC FEATURES (+ CVE-2023-33127)

Diagnostic applications interface and communicate with a target application’s CLR diagnostic port to send commands and receive responses. Graciously, Microsoft has released a suite of diagnostic tools and an API for interfacing with the diagnostic port.
诊断应用程序与目标应用程序的 CLR 诊断端口进行接口和通信,以发送命令和接收响应。Microsoft发布了一套诊断工具和一个用于与诊断端口接口的API。

DIAGNOSTIC APPLICATIONS & TOOLS
诊断应用和工具

The following Microsoft signed command line applications are available to diagnose .NET application issues:
以下 Microsoft 签名的命令行应用程序可用于诊断 .NET 应用程序问题:

  • dotnet-counters
  • dotnet-dump
  • dotnet-monitor
  • dotnet-trace
  • …and more

As you can imagine, some of these utilities can be used for living-off-the-land/lolbin scenarios. For instance, dotnet-dump instructs the CLR of a target .NET application to dump its process memory. Dotnet-dump also implements MiniDumpWriteDump, which can be used to create process minidumps of non-.NET processes (e.g. such as LSASS):

ABUSING .NET CORE CLR DIAGNOSTIC FEATURES (+ CVE-2023-33127)

DIAGNOSTIC API 诊断 API

Although command-line diagnostic tools provide a turnkey approach for diagnosing .NET applications, Microsoft makes available the Microsoft.Diagnostics.NETCore.Client API to interact with the diagnostic port of .NET applications for deeper use cases. The API is relatively straight forward to use and includes a diagnostic class and several methods for:
尽管命令行诊断工具提供了用于诊断 .NET 应用程序的统包方法,但 Microsoft 提供了 Microsoft。诊断。NETCore.Client API,用于与 .NET 应用程序的诊断端口进行交互,以实现更深入的用例。该 API 使用起来相对简单,包括一个诊断类和几种方法:

  • Setting environment variables
    设置环境变量
  • Dumping the .NET process
    转储 .NET 进程
  • Setting a startup CLR profiler
    设置启动 CLR 探查器
  • Attaching a CLR profiler…
    正在附加 CLR 探查器…
ABUSING .NET CORE CLR DIAGNOSTIC FEATURES (+ CVE-2023-33127)

Interestingly, a “monitoring” application can leverage API diagnostic port to instruct the target application CLR to attach a profiler. Leveraging the API, the following C# code snippet serves as “injector” to load a “profiler” DLL into a running process using the AttachProfiler() method:
有趣的是,“监视”应用程序可以利用 API 诊断端口来指示目标应用程序 CLR 附加探查器。利用 API,以下 C# 代码片段充当“注入器”,使用 AttachProfiler() 方法将“探查器”DLL 加载到正在运行的进程中:

using Microsoft.Diagnostics.NETCore.Client;

class profiler_injector
{
    static void Main(string[] args)
    {
        int pid = Int32.Parse(args[0]);
        string profilerPath = args[1];

        AttachProfiler(pid, Guid.NewGuid(), profilerPath);
    }

    static void AttachProfiler(int processId, Guid profilerGuid, string profilerPath)
    {
        var client = new DiagnosticsClient(processId);
        client.AttachProfiler(TimeSpan.FromSeconds(10), profilerGuid, profilerPath);
    }
}

Expectedly, running the injector programs shows a successful result:
预期,运行喷油器程序会显示成功的结果:

ABUSING .NET CORE CLR DIAGNOSTIC FEATURES (+ CVE-2023-33127)

IPC MESSAGING PROTOCOL IPC 消息传递协议

The Diagnostic IPC Protocol is used for client (“monitoring application”) and server (target application CLR) messaging over the diagnostic port named pipe. Microsoft provides excellent documentation of the transport, structure, and commands. Leveraging the IONinja protocol analyzer, an example client request and server response for issuing the AttachProfiler command appears as follows:
诊断 IPC 协议用于通过名为管道的诊断端口进行客户端(“监视应用程序”)和服务器(目标应用程序 CLR)消息传递。Microsoft 提供了有关传输、结构和命令的出色文档。利用 IONinja 协议分析器,发出 AttachProfiler 命令的客户端请求和服务器响应示例如下所示:

ABUSING .NET CORE CLR DIAGNOSTIC FEATURES (+ CVE-2023-33127)

The “magic” string value effectively serves as the message header, and it has a 14-byte reservation. As of this blog release date, the constant magic value is “DOTNET_IPC_V1”. The following two bytes are reserved for the payload size, and the next two bytes are reserved for the command code.
“magic”字符串值有效地用作消息标头,并且它有一个 14 字节的保留。截至本博客发布日期,恒定的魔术值为“DOTNET_IPC_V1”。以下两个字节保留用于有效负载大小,接下来的两个字节保留用于命令代码。

For the client message, 0x0301 is the identifier for the AttachProfiler command. The next two bytes are generally reserved, and the remainder of the message is the payload. In this case, the client payload data includes the attachment timeout value, a CLSID/GUID value (e.g. for the CORECLR_PROFILER), and the path to the profiler DLL (e.g. for CORECLR_PROFILER_PATH). The remaining bytes are not set, but other messages may contain a client data element.
对于客户端消息,0x0301 是 AttachProfiler 命令的标识符。接下来的两个字节通常是保留的,消息的其余部分是有效负载。在这种情况下,客户端有效负载数据包括附件超时值、CLSID/GUID 值(例如,对于CORECLR_PROFILER)和探查器 DLL 的路径(例如,对于CORECLR_PROFILER_PATH)。未设置剩余的字节,但其他消息可能包含客户端数据元素。

For this example, the command code in the server response (0xFFFF) is interesting. Although the “profiler” DLL successfully attaches, the command code indicates an error with the DLL since it is not a true profiler DLL. In this case, the DLL does not adhere to the expected structure and is evicted.

Note: With insight into the messaging protocol, one could go a step further and forgo managed API usage and craft diagnostic IPC messages at the byte-code level.

CVE-2023-33127: .NET CROSS SESSION LOCAL PRIVILEGE ESCALATION

MOTIVATION

Every now and again, researching offensive tradecraft opens the door for thinking of new ways to exploit potential vulnerabilities. The CLR diagnostic attack surface was interesting, especially with the capabilities provided by the CLR and use of named pipes for IPC endpoint. Initially, I did not identify any formal services operating in a privileged context (e.g. NT AUTHORITY\SYSTEM) that leveraged .NET Core. Eventually, I found a few third-party services as well as use within Azure pipelines, but the UWP apps were all I had to work with at the time. I noted two possible use cases for privilege elevation:

  • An observation was made that some UWP apps operated in low integrity. There may be a scenario to potentially elevate from low to medium integrity within a user session.
    据观察,某些 UWP 应用以低完整性运行。可能存在一种情况,可能会在用户会话中将完整性从低度提升到中度。
  • Other UWP apps operate at medium integrity. UWP processes are created for each user logged into a machine. It may be possible to influence the UWP application diagnostic port that is created in another user’s session.
    其他 UWP 应用以中等完整性运行。UWP 进程是为登录到计算机的每个用户创建的。可能会影响在其他用户的会话中创建的 UWP 应用程序诊断端口。

I opted to start with the latter as I always found cross-session attacks to be very interesting.
我选择从后者开始,因为我总是发现跨会话攻击非常有趣。

DISCOVERY METHODOLOGY 发现方法论

Having already spent too many unhealthy years looking at Component Object Model (COM) and following the incredible research of James Forshaw (@tiraniddo), it was most natural place to look for cross-session attack opportunities. It is no secret that users can activate DCOM objects in other interactive sessions. This includes a scenario when a non-privileged users is logged into the same machine as a privileged user.
在花了太多不健康的岁月研究组件对象模型 (COM) 并遵循 James Forshaw (@tiraniddo) 令人难以置信的研究之后,寻找跨会话攻击机会是最自然的地方。用户可以在其他交互式会话中激活 DCOM 对象,这已经不是什么秘密了。这包括非特权用户与特权用户登录到同一台计算机的情况。

Cross session activation is made possible when the identity of the target DCOM object is set to run as the “interactive user” (e.g. the interactive user in the target session), and the activation and launch permissions permit the object activation to occur by the launching user (e.g. the attacker).
当目标 DCOM 对象的身份设置为以“交互式用户”身份运行(例如目标会话中的交互式用户)运行时,跨会话激活成为可能,并且激活和启动权限允许启动用户(例如攻击者)进行对象激活。

ABUSING .NET CORE CLR DIAGNOSTIC FEATURES (+ CVE-2023-33127)

Note: Even if DCOM security settings permit object activation in another session, it does not necessarily mean the launching user has the permissions to access and use the activated object. Regardless, activation is all that is required for this use case.
注意:即使 DCOM 安全设置允许在另一个会话中激活对象,也不一定意味着启动用户有权访问和使用激活的对象。无论如何,此用例只需要激活即可。

Fortunately for us, James developed and released OleViewDotNet, which makes discovering and analyzing COM objects much easier and quicker. After narrowing down COM objects configured to run as the “interactive user”, I discovered that the Phone Link UWP application (PhoneExperienceHost.exe) was also a DCOM server:

ABUSING .NET CORE CLR DIAGNOSTIC FEATURES (+ CVE-2023-33127)

After some basic testing, two key elements came to fruition:

  • As an out-of-process DCOM server, associated DCOM class objects would launch the PhoneExperienceHost.exe executable (including all .NET components).
    作为进程外 DCOM 服务器,关联的 DCOM 类对象将启动 PhoneExperienceHost.exe 可执行文件(包括所有 .NET 组件)。
  • A lower privileged user could most certainly activate several associated DCOM objects in a privileged user session on Windows 10 (e.g. CLSID – 7540C300-BE9B-4C0D-A335-F002F9AB73B7).
    较低权限的用户肯定可以在 Windows 10 上的特权用户会话中激活多个关联的 DCOM 对象(例如 CLSID – 7540C300-BE9B-4C0D-A335-F002F9AB73B7)。

Although a potential premise was set for cross-session attack, there was still the problem of lacking a core exploitation vector. There are several ways to approach this problem, and I thought about investigating a few of those potential vectors, but I focused on the diagnostic port named pipe. There are interesting exploitation primitives that could potentially be leveraged to attack named pipes as discussed in this fantastic blog post by @0xcsandker.
尽管为跨会话攻击设定了潜在的前提,但仍然存在缺乏核心利用媒介的问题。有几种方法可以解决这个问题,我考虑过研究其中的一些潜在向量,但我专注于名为 pipe 的诊断端口。正如 @0xcsandker 在这篇精彩的博客文章中所讨论的那样,有一些有趣的利用原语可能会被利用来攻击命名管道。

Albeit an obvious statement – one of the best things about open-source software is that the source code is made publicly available, so there is a time advantage for not having to reverse engineer part of the .NET runtime and/or dive too deeply into the internals (although it is not a bad idea). As such, I decided to search through the .NET runtime source code on GitHub and analyze the diagnostic port implementation. Here is the C code used to create the named pipe with CreateNamedPipeA (prior to patching):
尽管这是一个显而易见的声明——开源软件最好的事情之一就是源代码是公开的,因此不必对 .NET 运行时的一部分进行逆向工程和/或深入研究内部结构是有时间优势的(尽管这不是一个坏主意)。因此,我决定在 GitHub 上搜索 .NET 运行时源代码并分析诊断端口实现。下面是用于使用 CreateNamedPipeA 创建命名管道的 C 代码(在修补之前):

ABUSING .NET CORE CLR DIAGNOSTIC FEATURES (+ CVE-2023-33127)

Named pipes are FIFO structures – the first named pipe server instance has precedence to respond to client requests if multiple named pipes with the same name exist. Furthermore, subsequent named pipes inherit the handle security descriptor of the first named pipe when created, including the DACL and ownership. However, if the FILE_FLAG_FIRST_PIPE_INSTANCE flag is specified within the openmode parameter, the subsequent named pipe will not be created, and inheritance will be thwarted.
命名管道是 FIFO 结构 – 如果存在多个同名命名管道,则第一个命名管道服务器实例优先响应客户端请求。此外,后续命名管道在创建时会继承第一个命名管道的句柄安全描述符,包括 DACL 和所有权。但是,如果在 openmode 参数中指定了 FILE_FLAG_FIRST_PIPE_INSTANCE 标志,则不会创建后续命名管道,并且继承将受阻。

Interestingly, the FILE_FLAG_FIRST_PIPE_INSTANCE flag is not specified when creating the diagnostic port named pipe. This means that the named pipe will still be created even if another pipe with the same name already exists. In short, if an attacker creates a crafted named pipe before the Core CLR creates a diagnostic port with the same name, the attacker has the ability to control the diagnostic endpoint and issue commands from another session because the attacker owns the named pipe handle and security descriptor. To successfully exploit this condition, the attacker must figure out a way to create the malicious named pipe prior to the .NET application CLR runtime creating the legitimate named pipe of the same name.
有趣的是,在创建名为 pipe 的诊断端口时,未指定 FILE_FLAG_FIRST_PIPE_INSTANCE 标志。这意味着,即使已存在另一个同名管道,仍将创建命名管道。简而言之,如果攻击者在核心 CLR 创建具有相同名称的诊断端口之前创建构建的命名管道,则攻击者能够控制诊断终结点并从另一个会话发出命令,因为攻击者拥有命名管道句柄和安全描述符。若要成功利用此情况,攻击者必须在 .NET 应用程序 CLR 运行时创建同名的合法命名管道之前找到创建恶意命名管道的方法。

Note: In my recorded MCTTP conference talk, I misspoke about the inclusion of the PIPE_UNLIMITED_INSTANCES flag when it should have been about the exclusion of the FILE_FLAG_FIRST_PIPE_INSTANCE flag. Please execute this error if you decide to watch the recorded talk.

Now, let’s recall the naming convention for the diagnostic port named pipe:
现在,让我们回想一下名为 pipe 的诊断端口的命名约定:

\.\pipe\dotnet-diagnostic-{Process ID (PID) of .NET application}

Although the named pipe is mostly static, the suffix mirrors the process identifier of the running .NET application. As a result, there are three challenges to overcome for successful exploitation:
尽管命名管道大多是静态的,但后缀反映了正在运行的 .NET 应用程序的进程标识符。因此,要成功利用,需要克服三个挑战:

  1. Beat a race condition and create the tampered named pipe before the target .NET application.
    击败争用条件,并在目标 .NET 应用程序之前创建被篡改的命名管道。
  2. Figure out a continuous way to spawn the target process until a named pipe match is made.
    找出一种连续的方式来生成目标进程,直到进行命名管道匹配。
  3. And finally, deliver a payload…
    最后,交付有效载荷……

EXPLOITATION WALKTHROUGH
漏洞利用演练

Fortunately, all of the challenges can be addressed programmatically with the required conditions in place. First order of business was to address the race condition, which in many ways is out of our control, so my solution was to optimize coverage and leverage a “spray and pray” technique. For a proof-of-concept, I opted to create thousands of weakly permissive named pipes conforming to the diagnostic port convention. After a restart, there was a likelihood of low-ordered PID creation for newly spawned target application processes, which slightly increased the chance of hitting the covered named pipes. In reality, this approach was not as practical as just accounting for different ranges of PIDs and maintaining a sense of realism (e.g. no reboot in the real world with multiple sessions). In the end, the best option was just to simply increase the number of tampered named pipes for getting a quicker match.
幸运的是,只要具备所需的条件,所有挑战都可以通过编程方式解决。首要任务是解决竞争条件,这在许多方面是我们无法控制的,因此我的解决方案是优化覆盖范围并利用“喷雾和祈祷”技术。为了进行概念验证,我选择创建数千个符合诊断端口约定的弱许可命名管道。重新启动后,可能会为新生成的目标应用程序进程创建低阶 PID,这略微增加了命中覆盖的命名管道的机会。实际上,这种方法并不像仅仅考虑不同范围的 PID 和保持真实感那样实用(例如,在现实世界中没有多个会话的重启)。最后,最好的选择只是简单地增加被篡改的命名管道的数量,以获得更快的匹配。

Next, the issue of continuous COM activation. Interestingly enough, activating a cross-session DCOM object is quite easy through the use of a Session Moniker:
接下来,是连续 COM 激活的问题。有趣的是,通过使用会话名字对象,激活跨会话 DCOM 对象非常容易:

Format: Session:[session id]!clsid:[class id]

I opted to continuously activate target DCOM object in an infinite loop. A sleep delay was added to ensure that the same, previously activated object was not re-used so that a new out-of-process server in the target session was spawned to increase the chance of a match.
我选择在无限循环中连续激活目标 DCOM 对象。添加了睡眠延迟,以确保不会重复使用以前激活的相同对象,从而在目标会话中生成新的进程外服务器,以增加匹配的机会。

Lastly, I needed a payload delivery vector. This was the best part – simply re-using the AttachProfiler capability to deliver a malicious DLL payload worked like a charm after cleaning up the malicious named pipe.
最后,我需要一个有效载荷交付向量。这是最好的部分 – 在清理恶意命名管道后,只需重用 AttachProfiler 功能来提供恶意 DLL 有效负载,就像魅力一样。

DEMONSTRATION 示范

Here is a screenshot of the exploit in action:
以下是该漏洞的屏幕截图:

ABUSING .NET CORE CLR DIAGNOSTIC FEATURES (+ CVE-2023-33127)

Once the .NET target process created the diagnostic port named pipe after a match, the handle inherited weak DACL permissions and ownership from the tampered named pipe:
一旦 .NET 目标进程在匹配后创建了名为 pipe 的诊断端口,句柄就会从被篡改的命名管道继承弱 DACL 权限和所有权:

ABUSING .NET CORE CLR DIAGNOSTIC FEATURES (+ CVE-2023-33127)

Upon successful tampering, the exploit sends the AttachProfiler command to the target .NET application diagnostic endpoint and instructs the CLR to load the payload DLL to achieve cross-session code execution:
成功篡改后,该漏洞会将 AttachProfiler 命令发送到目标 .NET 应用程序诊断终结点,并指示 CLR 加载有效负载 DLL 以实现跨会话代码执行:

ABUSING .NET CORE CLR DIAGNOSTIC FEATURES (+ CVE-2023-33127)

MITIGATION & DISCLOSURE TIMELINE
缓解和披露时间表

  • 03/2023 – Initial report submitted to MSRC
    03/2023 – 向 MSRC 提交初步报告
  • 04/2023 – Acknowledgement of vulnerability and patch development
    04/2023 – 确认漏洞和补丁开发
  • 06/2023 – Unofficially, Microsoft appeared to address launch and activation permissions for the impacted DCOM objects
    06/2023 – 非正式地,Microsoft 似乎解决了受影响的 DCOM 对象的启动和激活权限
  • 07/2023 – Official patch released (in .NET) by Microsoft
    07/2023 – Microsoft 发布官方补丁(在 .NET 中)
  • 09/2023 – Bug initially disclosed at the 2023 MCTTP conference
    09/2023 – 最初在 2023 年 MCTTP 会议上披露的错误

DEFENSIVE CONSIDERATIONS
防御注意事项

  • To protect against CVE-2023-33127 cross-session privilege escalation, upgrade .NET dependency components to the latest version. The patch was officially addressed in July 2023.
    若要防止 CVE-2023-33127 跨会话权限提升,请将 .NET 依赖项组件升级到最新版本。该补丁已于 2023 年 7 月正式解决。
  • To prevent the .NET Core CLR diagnostic port from loading at all, set persistent environment variables at all applicable levels with the following configuration knob:
    若要完全防止加载 .NET Core CLR 诊断端口,请使用以下配置旋钮在所有适用级别设置持久性环境变量:
DOTNET_EnableDiagnostics=0
  • To detect possible dotnet-dump.exe lolbin abuse, consider implementing the following SIGMA rule authored by Nasreddine Bencherchali (@nas_bench): proc_creation_win_lolbin_dotnet_dump
    若要检测可能的 dotnet-dump.exe lolbin 滥用,请考虑实现以下由 Nasreddine Bencherchali (@nas_bench) 编写的 SIGMA 规则: proc_creation_win_lolbin_dotnet_dump
  • To detect possible Environment Variable CoreCLR profiler abuse, consider implementing the following updated SIGMA rule originally authored by Jose Rodriguez (@Cyb3rPandaH): registry_set_enabling_cor_profiler_env_variables
    若要检测可能的环境变量 CoreCLR 探查器滥用,请考虑实现最初由 Jose Rodriguez (@Cyb3rPandaH) 编写的以下更新的 SIGMA 规则: registry_set_enabling_cor_profiler_env_variables
  • Understanding .NET telemetry sources are important for collecting events and building robust detections. Telemetry Layering by Jonny Johnson (@jsecurity101) is a great resource that dives into the concept. As such, consider leveraging .NET (Core) diagnostic capabilities to aid in telemetry collection if feasible for your use cases. Monitor for interesting and opportunistic CLR events (e.g. profiler attachment) in addition to other interesting events such as .NET assembly loads.
    了解 .NET 遥测源对于收集事件和生成可靠的检测非常重要。Jonny Johnson ( @jsecurity101) 的 Telemetry Layering 是深入研究该概念的绝佳资源。因此,如果用例可行,请考虑利用 .NET (Core) 诊断功能来帮助进行遥测收集。监视有趣和机会主义的 CLR 事件(例如探查器附件),以及其他有趣的事件(如 .NET 程序集加载)。

CONCLUSION 结论

.NET presents an interesting and opportunistic attack surface. In this post, we focused on Windows techniques, but there are certainly use cases that may extend to or present unique opportunities on other platforms and operating systems.
.NET 提供了一个有趣且机会性的攻击面。在这篇文章中,我们重点介绍了 Windows 技术,但肯定有一些用例可能会扩展到其他平台和操作系统或在其他平台上提供独特的机会。

As always, thank you for taking the time to read this post and happy hunting!
一如既往,感谢您抽出宝贵时间阅读这篇文章,祝您狩猎愉快!

-bohops -波霍普斯

 

原文始发于BOHOPS:ABUSING .NET CORE CLR DIAGNOSTIC FEATURES (+ CVE-2023-33127)

版权声明:admin 发表于 2023年11月28日 下午9:42。
转载请注明:ABUSING .NET CORE CLR DIAGNOSTIC FEATURES (+ CVE-2023-33127) | CTF导航

相关文章

暂无评论

您必须登录才能参与评论!
立即登录
暂无评论...