By Malcolm Stagg
CVE-2021-34535 is a Remote Code Execution (RCE) vulnerability in Remote Desktop Client, found by SRT member Malcolm Stagg earlier this year, and patched by Microsoft in August 2021.
Finding the Vulnerability
I found this vulnerability by looking at the disassembly of several Windows dll’s in IDA debugger for potential memory access flaws. Protocol parsing code, especially code involving multimedia decoding, tends to be a common place for flaws since the protocol decoding is often complex. When raw pointers to memory buffers are used directly, it is easy to make a mistake that can lead to a serious memory access vulnerability.
Looking at occurrences of memcpy, the C function that copies data between two memory buffers, I found one occurrence in the TSMF media decoder that showed signs of having a complex access pattern. TSMF is a legacy plug-in for Remote Desktop, in which the Remote Desktop Server transfers a multimedia file to be played by the Remote Desktop Client.
First, the decoder allocates a heap buffer with the size cbData+63 bytes, where cbData is a field from a packet that attackers can control. Next, cbData+36 bytes of data are copied from the packet into the buffer. The remaining 27 bytes are intended to be filled with data from a separate buffer.
This access pattern looks innocent enough until you look at cases involving an integer overflow. cbData is a 32-bit unsigned integer, so it can represent any number between 0 and approximately 4 billion. By specifying a buffer size just slightly below that upper limit, an integer overflow will occur, causing a very small buffer to be allocated, and a huge amount of attacker-controlled data copied into that buffer. The result is a heap buffer overflow, where structures throughout the program’s memory space are overwritten with attacker-controlled data.
Exploiting the Vulnerability
There are two main scenarios for how an attacker could exploit this vulnerability. One of these is by gaining control of a Remote Desktop Server. An attacker could take control of a victim’s machine when it connects to the malicious Remote Desktop Server, exploiting this vulnerability to run code that escapes from the Remote Desktop Client onto the victim’s machine.
The other scenario, which is perhaps even more interesting, is a Hyper-V Client escape. Unless “Enhanced Session Mode” is explicitly disabled by the user, Hyper-V uses Remote Desktop Client dll’s while accessing a virtual machine. By doing so, features like clipboard sharing and printing are enabled, improving the user experience. If a virtual machine is running malicious software, an attacker could exploit this vulnerability to escape from the Hyper-V Client and gain control over the host machine. Since users often run untrusted software inside a virtual machine to provide better security and isolation, this is an interesting case that could have a serious impact.
Proof of Concept
The vulnerability was fairly difficult to exploit for two reasons: one is that it will always result in a client crash. Approximately 4 GiB of data is copied into an extremely small buffer, so a memory access violation is inevitable. The attacker’s payload must be successfully executed before the client crash occurs.
The other difficulty in exploitation is due to Address Space Layout Randomization (ASLR), a security feature designed to make memory access vulnerabilities more difficult to exploit by providing randomization of memory addresses. Since this vulnerability in itself provides no way of bypassing ASLR, for the purposes of demonstration, it is assumed that the attacker has some other way of bypassing it. A common method would be finding an information disclosure vulnerability where a program’s internal memory pointers are exposed to the attacker.
Ultimately, a proof of concept was developed by finding a target function where Hyper-V Client jumps to a memory address stored within the attack payload. To obtain remote code execution, a couple of “gadget” functions were also found. Gadgets are existing functions within the program which have been repurposed by the attacker to perform a task.
The first gadget causes a memory pointer to jump from its initial, random, location within the attack payload to a specific location known to the attacker. This known location specifies a second gadget function and a program name. The second gadget function causes the program name to be read from the attack payload and executed.
The proof of concept is demonstrated in the following video, showing how executing a program within a virtual machine can result in a Calculator executing on the host machine.
Preventing These Vulnerabilities
This specific vulnerability could have been prevented by the developers performing several additional validation checks:
- Validate all user-controlled data and buffer sizes
- Check for integer overflow edge cases
- Verify a buffer’s length before copying any data
Memory access vulnerabilities are most common when using raw pointers directly, so those should be avoided whenever it’s feasible to do so.
If you’re accessing an untrusted virtual machine in Hyper-V or running an untrusted program on your virtual machine, disable “Enhanced Session Mode” whenever you can to reduce your attack surface.
Always be cautious when accessing a Remote Desktop Server you don’t explicitly trust. It is best to only access machines with which you are familiar.
Finally, by keeping your computer up-to-date and installing the latest Windows Update patches, your computer will be protected from many new vulnerabilities, including this one!