Skip Navigation

June 8, 2023 |

[CVE Analysis] Red October: One Ping Too Many

Loading table of contents...

Details of a critical TCP/IP RCE and more

Developing a security product for Windows involves gaining detailed knowledge of the operating system internals, often beyond what is available in published documentation, and which can only be obtained by reverse engineering.

While doing research for our Covalence endpoint agent in September and October of 2022, I discovered several security vulnerabilities in the Windows operating system.

Microsoft verified and reported these vulnerabilities in October and November, and patched them in January and March 2023. There were three critical/important bugs reported:

  • Privilege escalation in Advanced Local Procedure Call (ALPC)
  • Remote code execution through Personal Information Exchange (PFX) files
  • Unauthenticated network remote code execution in TCP/IP driver

Before we dive into the details of each vulnerability and its impact, we recommend keeping all your Windows devices up to date to ensure you are as secure as possible.

ALPC CVE-2023-21688

CVSS 7.8 / Important

My previous research into Windows ALPC internals resulted in the discovery of multiple privilege escalation bugs. You can read the full write-up here.

After doing the ALPC research last year, I revisited the code. Often a fresh mindset will uncover different types of bugs. This led to the discovery of a Use-After-Free (UAF) race condition. Interestingly, shortly after I found this UAF, two more race conditions in ALPC were patched:

  • CVE-2022-38029
  • CVE-2022-34725

Both times I assumed it was a bug collision until I was able to try out the Proof of Concept (PoC) on a patched system. All three ALPC bugs are race conditions leading to UAF in ALPC Port or Section View creation.

ALPC provides a performance enhancement mechanism to share memory between client and server processes with sections and views. From Microsoft Developer Network (MSDN):

A section object represents a section of memory that can be shared. A process can use a section object to share parts of its memory address space (memory sections) with other processes.

and

Each memory section has one or more corresponding views. A view of a section is a part of the section that is actually visible to a process.

When an application creates an ALPC port, it can create sections and views for the port. Internally, the sections and views are represented with reference counted objects called blobs. ALPC blobs can be associated with the port they are created on, with the AlpcpInsertResourcePort function. When view objects are created, the virtual address they get mapped to is returned to the user mode application. This address can be used to reference the view in future ALPC calls, such as NtAlpcDeleteSectionView.

During view creation, there is a period of time where the object is exposed to user mode but before the reference count is increased. If a malicious application predicts the virtual address for a view and deletes the view object in this window of time, then a UAF vulnerability occurs. Predicting the virtual address for a view is trivial as the same addresses are reused, so an application can create a view to get the address, delete it, and create another which will be given the same address.

To achieve the UAF condition:

  1. Create a thread to continually call NtAlpcDeleteSectionView with the predicted view address to race the create call.
  2. Create a section view object with the NtAlpcCreateSectionView application programming interface (API).
  3. Trigger large numbers of kernel allocations to try and reclaim the freed view.
  4. If the race failed, repeat from Step #2.

The view object that is targeted contains pointers to other objects that can be controlled and used to gain both an arbitrary read primitive and invoke an arbitrary function. These two primitives are enough to gain full privilege escalation using this vulnerability. This could allow any malicious code running on a computer, even fully sandboxed applications, to obtain access to the entire system (including credentials for any logged-on users).

One interesting note on this vulnerability is that part of Microsoft’s Security Development Lifecycle (SDL) process is supposed to be checking for similar bugs when fixing vulnerabilities through variant analysis. But in this case, three very similar bugs in ALPC were externally reported and fixed over four or five months and not found during the review by Microsoft.

NCryptUnprotectSecret CVE-2023-23416

CVSS 8.4 / Critical

This bug is deep within the Windows Cryptography system. The NCryptProtectSecret API can be used to encrypt data (typically passwords, key material, etc.) for a specific protection descriptor. Protection descriptors describe the entities that can access the encrypted data and are created with NCryptCreateProtectionDescriptor. Multiple entities can be defined by using the "AND" keyword, e.g., "SID=S-1-X-X AND SID=S-1-Y-Y". The output of NCryptProtectSecret is an ASN.1 encoded blob including the descriptor definition and the encrypted secret.

When creating protection descriptors and encrypting using the provided APIs, there is a limit of eight entities that can be combined with the "AND" keyword. However, if an ASN.1 encoded secret is manually created with more than eight entities in the protection descriptor, then a stack buffer overflow will occur when the secret is unpacked using NCryptUnprotectSecret. During the unwinding of the function with the corrupted stack, I_GetDescriptorFromAndCombiner, it will free the same buffer(s) more than once causing a crash.

The image below shows the debugger (windbg) output from the crash:

Text Box

There are several code paths to this bug, with the most interesting being through the Encrypted File System (EFS), a Terminal Services ActiveX control, and parsing of PFX certificate files. I only tried triggering the bug with PFX files, but it may also be possible via EFS encrypted files on a USB stick or RDP settings files.

IP Options Header Parsing CVE-2023-23415

CVSS 9.8 / Critical

This vulnerability is in the processing of the options header in an IPv4 packet. In order to trigger the vulnerability, the packet must be fragmented which is not possible in the standard IPv4 receive path. However, it can be reached if IPsec tunnels are in use or if an application is using a raw socket.

Here's a video of the vulnerability I shared on Twitter earlier this year:

202303_poc_twitter (1) (1)

The Microsoft bulletin for this vulnerability, described it as a bug parsing an ICMP packet while raw sockets are being used. This is not completely accurate in my opinion, and the bug is slightly wider reaching than initially described.

The Windows TCP/IP stack handles packet data using NET_BUFFER structures, which can contain chains of memory buffers to make up entire packets. This increases performance by reducing the number of copies required for processing and sending network data. When fragmented IP packets are received, the data from each fragment is stored in separate buffers and all are referenced by the NET_BUFFER structure. Drivers processing incoming packet data must safely handle fragmented data. In some cases, an IPv4 packet header is one, the incoming is guaranteed not to be fragmented.

Figure 2: Diagram of NET_BUFFER structure

ICMP error packets are sent to indicate low-level protocol errors. In some cases, the body of these error packets will contain a copy of the original packet which caused the error. Normally IP headers are guaranteed to not be fragmented, but the IP packet header in the body of the ICMP error message does not have this guarantee. If a fragmented ICMP error packet is received, the driver may read past the end of the fragment buffer while parsing IP header options.

To reach this code path on a basic Windows install, ICMP must be allowed through the firewall and an application on the target must have bound to a raw socket. In this scenario, the ProcessIcmpErrorClassify function can be reached, which then calls Ipv4ProcessOptionsHelper on the IP packet that is being reported as having an error. Because this error IP packet is in the body of the ICMP message, it no longer has any guarantees about whether its IPv4 header is fragmented or not.

As mentioned previously, there are other ways to reach the vulnerability if a raw socket is not in use. If an IPsec tunnel has been created, then a forwarded ICMP error packet can hit the following functions…

IPSecParseFwdPacket() -> IPSecParseFwdPktForTransportLayerData() -> IPSecParseFwdPktIcmp() -> IPsecParseFwdPktIcmpError() -> IppInspecSkipNetworkLayerHeaders() -> Ipv4pSkipNetworkLayerHeaders() -> Ipv4ProcessOptionsHelper()

…and trigger the vulnerability.

The format of IPv4 header options consists of a type byte followed by a length byte. The incoming ICMP error packet can be fragmented in such a way that an options header is right at the end of the fragment buffer and will cause Ipv4ProcessOptionsHelper to read past the end of the buffer. If this buffer happens to be near a page boundary where the following page is not mapped, then a Blue Screen of Death (BSOD) will occur.

Figure 3 Fragmented ICMP Error Packet

You may have noticed that the vulnerability described results in an Out-Of-Bounds (OOB) read, which is a Denial-of-Service (DOS) vulnerability and not an RCE as reported. However, there are other code paths to Ipv4ProcessOptionsHelper. If the second parameter to this function is non-NULL while processing a fragmented packet with IP timestamp options, then a write past the end of the buffer will occur in Ipv4pProcessTimestampOption.

I was unable to reach a code path that triggered this OOB write, but almost two months after Microsoft confirmed the vulnerability which I submitted as a DOS, they raised the severity to an RCE. So, either MSRC is being *very* conservative with their vulnerability classification or they were able to reach the RCE code path. My guess is that there may be a way to get a fragmented IPv4 header to this code when IPsec is being used.

It is very difficult to turn a remote memory corruption vulnerability (such as this) into a usable working exploit. However, the potential impact is also very high as it would allow an attacker to gain full access to a vulnerable system over the network, bypassing many layers of security controls.

Avoiding a compromise

Any non-trivial software is guaranteed to have bugs, some of which will be security vulnerabilities. If an attacker discovers the vulnerabilities before the vendor or if security patches are not applied promptly then a compromise can occur.

These vulnerabilities highlight the importance of keeping software up to date with security patches as well as having a 24x7 cybersecurity solution in place to detect malware and other threats.