In this article, part one of the series, I describe the MultiValuedProperty exploitation primitive, which became fundamental for my further exploitation of Exchange PowerShell. I also present a bypass for Microsoft’s first patch for this vulnerability, accomplished by chaining MultiValuedProperty with the Command class.
Introduction
You might already be familiar with the Exchange ProxyNotShell chain, CVE-2022-41040 and CVE-2022-41082. It allowed any authenticated Exchange user to achieve remote code execution. ProxyNotShell was exploited in the wild before Microsoft released a patch.
I described the ProxyNotShell chain, especially its RCE vector, in this blog post. Before proceeding with this post, please make sure that you are familiar with the original issue, as this article will focus on bypassing the patches.
In this blog post, I would like to start with 2 RCE vulnerabilities:
• ZDI-23-163/ CVE-2023-21529 – abuse of the allowed MultiValuedProperty class.• ZDI-23-881/ CVE-2023-32031 – bypass for CVE-2023-21529, abuse of not blocked Command class.
Accessing PowerShell Without ProxyShell Path Confusion
The original path confusion vulnerability, CVE-2021-34473, was discovered by Orange Tsai. He used it together with CVE-2021-34523 and CVE-2021-31207 to achieve pre-auth remote code execution, forming the chain known as ProxyShell.
Microsoft’s original patch for the path confusion did not eliminate the root of the problem, but instead placed it behind authentication. After the patch, it was exploited in the wild for post-auth remote code execution using the ProxyNotShell chain mentioned above.
Exploitation of the path confusion allowed a threat actor to reach the Exchange PowerShell backend by sending HTTP requests to the autodiscover endpoint.
After the patch for ProxyNotShell, it appears that this attack vector is completely blocked, though I must admit that I have never fully verified that patch. Nonetheless, a low-privileged attacker still has direct access to Exchange PowerShell Remoting, subject to Kerberos authentication. This is because every Exchange user can trigger some Exchange PowerShell cmdlets, such as Get-Mailbox. Instructions that describe direct interaction with the Exchange PowerShell can be found here.
As Kerberos authentication is required, this attack surface is probably restricted to internal attackers, which is to say, attackers who are already present in the organization’s network. There remains plenty of reason for concern, though. It would not be good if any domain account (and organization member) could escalate to SYSTEM on the Exchange server.
Patch for the ProxyNotShell CVE-2022-41082 RCE
CVE-2022-41082, the RCE part of the ProxyNotShell chain, was fixed with the introduction of the Microsoft.Exchange.Diagnostics.UnitySerializationHolderSurrogateSelector class. It extends SurrogateSelector and its main goal is to validate the types that are retrieved during the deserialization of UnitySerializationHolder. It does this by checking the types against an allow list.
Microsoft’s approach here seems appropriate. An allow list is probably the best way to fight deserialization issues and similar type-based vulnerabilities. However, when the allow list is extensive, it may be possible to find some types there that can be used in exploitation. I decided to take this path and look for potentially dangerous allowed classes.
ZDI-23-162/ CVE-2023-21529 – Allowed MultiValuedProperty Leads to RCE
The Exchange allow lists can be divided into two main parts:• List of allowed regular types.• List of allowed generic types.
Generic types seem especially interesting because they allow the inclusion of arbitrary, internal types. Moreover, generic types can be also retrieved through a deserialization of UnitySerializationHolder. Let’s review the list of allowed generics that are defined in the Microsoft.Exchange.Data.SerializationTypeConverter.allowedGenerics member.