A vulnerability in the .NET Core library allows malicious programs to be launched while evading detection by security software.
This vulnerability is caused by a Path Traversal bug in Microsoft’s .NET Core library that allows malicious garbage collection DLLs to be loaded by users with low privileges.
This bug affects the latest stable release (3.1.x versions) of .NET Core. A fix is not currently available and could let attackers execute malicious code on a system without being readily detected by antivirus and EDR products. 1
Discovered by Paul Laîné of Context Information Security, the vulnerability is possible due to two main reasons:
.NET Core lets you use a custom DLL as its garbage collector
The environment variable “COMPlus_GCName” used for specifying a custom .NET garbage collector is not sanitized. Therefore any traversal characters (../) provided in the garbage collector path go unfiltered.
.NET Core uses a ‘garbage collector’ to allocate and free up system memory used by a .NET Core application.
It is possible, though, for users to create custom garbage collectors in the form of DLLs that will be loaded by a .NET core application.
.NET Core, though, allows any user, including those with low privileges, to load a custom garbage collector DLL, even those containing malicious code.
Exploiting this bug
Before exploiting this flaw, the attacker already needs to have at least some level of access to the system to set environment variables. That means this flaw would realistically be used in conjunction with an existing exploit, such as in a vulnerability chaining scenario.
The main incentive for a hacker to incorporate this attack in their toolkit would be to prevent their malicious payload from being detected by security software running on the compromised machine.
To exploit this bug, an attacker would first create a custom garbage collector containing malicious code that they want to execute on a compromised machine.
They then set an environment variable that causes .NET Core to use this customized DLL.
When loaded, the malicious code will be executed by the legitimate .NET Core process, dotnet.exe, under the impression that the DLL is merely a customized garbage collector.
Once the garbage collector DLL is loaded by the .NET Core framework, the payload begins execution, which in this cause is a reverse TCP shell.
In a real-world scenario, an attacker with access to a compromised machine can use a simple batch script to have .NET Core run their malicious DLL, without being detected.
Why can’t EDR products detect this?
The researchers at Pentest Laboratories further analyzed this vulnerability and provided additional insight.
The researchers explain that the exploit uses what’s known as a process hollowing technique.
“Paul Laîné in his proof of concept used the technique process hollowing to inject code into a legitimate process since the process is created in a suspended state, memory regions are not mapped to a file and are replaced by the actual shellcode,” explains the Pentest Laboratories blog post.
Because the malicious code execution happens under a legitimate process, this technique is useful in evading stringent detection and defense controls employed by security software products.
How to detect and remediate the evasive code execution?
Pentest Laboratories researchers have provided a couple of strategies for detecting if this vulnerability is being abused.
While it is nearly impossible to predict where the malicious garbage detector DLL resides on a system, the environment variable “COMPlus_GCName” remains a fixed string and can be monitored.
“Even though the name of the DLL file, the path, the process,and the .NET application are completely arbitrary the ‘COMPlus_GCName’ is a fixed string,” state the researchers.
The researchers provide a YARA rule which can be used to monitor for instances of “COMPlus_GCName” within the evasive processes:
Additionally, the researchers have provided Sysmon event IDs, which are sequentially created in environments where this vulnerability is being actively exploited.
Not a vulnerability, says Microsoft
Because the exploitation of this mechanism requires that the attackers to have already the ability to set environment variables on the compromised system, Microsoft does not consider this a security vulnerability:
“Per MSRC, we do not consider this to be a security vulnerability. Exploiting this would require the adversary to modify the environment block, at which point they’re already in control over other aspects of the application’s execution.”, stated Microsoft’s representative in the GitHub issue reported by Laîné.
Laîné acknowledged in his original disclosure, “Having the ability to use a custom GC is a legitimate feature and should probably not be removed. However, the path traversal should be addressed in order to limit the use of a custom GC to only users with local administrator privileges, which should be the case for a server-side application or in a development environment.”
Given there is no trivial fix for this “legitimate” feature, there remains the potential for abuse in .NET heavy enterprise environments.