🤬
  • ■ ■ ■ ■ ■ ■
    0day-RCAs/2021/CVE-2021-26855.md
     1 +# CVE-2021-26855: Microsoft Exchange Server-Side Request Forgery
     2 +*Anthony Weems, Michael Weber, Dallas Kaman*
     3 + 
     4 +## The Basics
     5 + 
     6 +**Disclosure or Patch Date:** March 2 2021
     7 + 
     8 +**Product:** Microsoft Microsoft Exchange Server
     9 + 
     10 +**Advisory:** https://msrc.microsoft.com/update-guide/vulnerability/CVE-2021-26855
     11 + 
     12 +**Affected Versions:** [Exchange 2010, 2013, 2016, and 2019](https://techcommunity.microsoft.com/t5/exchange-team-blog/march-2021-exchange-server-security-updates-for-older-cumulative/ba-p/2192020) before KB5000871.
     13 + 
     14 +**First Patched Version:** [KB5000871](https://support.microsoft.com/en-us/topic/description-of-the-security-update-for-microsoft-exchange-server-2019-2016-and-2013-march-2-2021-kb5000871-9800a6bb-0a21-4ee7-b9da-fa85b3e1d23b)
     15 + 
     16 +**Issue/Bug Report:** N/A
     17 + 
     18 +**Patch CL:** N/A
     19 + 
     20 +**Bug-Introducing CL:** N/A
     21 + 
     22 +**Reporter(s):** Volexity, [Orange Tsai](https://twitter.com/orange_8361) from [DEVCORE](https://devco.re) research team, and Microsoft Threat Intelligence Center (MSTIC)
     23 + 
     24 +## The Code
     25 + 
     26 +**Proof-of-concept:** https://github.com/praetorian-inc/proxylogon-exploit
     27 + 
     28 +**Exploit sample:** N/A
     29 + 
     30 +**Did you have access to the exploit sample when doing the analysis?** No
     31 + 
     32 +## The Vulnerability
     33 + 
     34 +**Bug class:** Server-Side Request Forgery (SSRF)
     35 + 
     36 +**Vulnerability details:**
     37 + 
     38 +*Note: This analysis relies upon source code obtained by decompiling the various .NET assemblies within Microsoft Exchange 2013.*
     39 + 
     40 +The Exchange frontend proxy is tricked into sending a request to an arbitrary backend endpoint authenticated via Kerberos as the Exchange server.
     41 + 
     42 +The `BEResourceRequestHandler` is used to handle requests for static resources within `/ecp` that pass the `IsResourceRequest` check. This function validates that the provided URL ends with one of many static file extensions (e.g. js, jpg, ico, png, ttf, etc.). Since this handler is within the frontend, it does not validate the full static file path and therefore a random filename with a `.js` suffix will be sent to this handler.
     43 + 
     44 +Requests in the frontend proxy are routed to the backend via "anchor mailboxes" (the `AnchoredRoutingTarget` field within `ProxyRequestHandler`). Each resource handler is responsible for returning an anchor mailbox to describe how its request should be routed. The `BEResourceRequestHandler` uses the following pseudo-code for its routing:
     45 + 
     46 +```csharp
     47 +protected override AnchorMailbox ResolveAnchorMailbox()
     48 +{
     49 + string cookie = BEResourceRequestHandler.GetBEResouceCookie(base.ClientRequest);
     50 + if (!string.IsNullOrEmpty(cookie))
     51 + {
     52 + return new ServerInfoAnchorMailbox(BackEndServer.FromString(cookie), this);
     53 + }
     54 + return base.ResolveAnchorMailbox();
     55 +}
     56 + 
     57 +private static string GetBEResouceCookie(HttpRequest httpRequest)
     58 +{
     59 + string result = null;
     60 + HttpCookie httpCookie = httpRequest.Cookies[Constants.BEResource];
     61 + if (httpCookie != null)
     62 + {
     63 + result = httpCookie.Value;
     64 + }
     65 + return result;
     66 +}
     67 +```
     68 + 
     69 +The `BEResourceRequestHandler` uses the `X-BEResource` cookie to construct a `BackEndServer` and then a `ServerInfoAnchorMailbox`. Pseudo-code for `BackEndServer` instantiation is shown below:
     70 + 
     71 +```csharp
     72 +public static BackEndServer FromString(string input)
     73 +{
     74 + string[] array = input.Split(new char[]{'~'});
     75 + int version;
     76 + if (array.Length != 2 || !int.TryParse(array[1], out version))
     77 + {
     78 + throw new ArgumentException("Invalid input value", "input");
     79 + }
     80 + return new BackEndServer(array[0], version);
     81 +}
     82 +```
     83 + 
     84 +Finally, this anchor mailbox is used within the `ProxyRequestHandler`'s `GetTargetBackEndServerUrl` function to resolve the actual `Uri` to use in the backend request. Pseudo-code for this method is shown below:
     85 + 
     86 +```csharp
     87 +protected virtual Uri GetTargetBackEndServerUrl()
     88 +{
     89 + // ...
     90 + UriBuilder clientUrlForProxy = new UriBuilder(this.ClientRequest.Url);
     91 + clientUrlForProxy.Scheme = Uri.UriSchemeHttps;
     92 + clientUrlForProxy.Host = this.AnchoredRoutingTarget.BackEndServer.Fqdn;
     93 + clientUrlForProxy.Port = 444;
     94 + if (this.AnchoredRoutingTarget.BackEndServer.Version < Server.E15MinVersion)
     95 + {
     96 + this.ProxyToDownLevel = true;
     97 + clientUrlForProxy.Port = 443;
     98 + }
     99 + return clientUrlForProxy.Uri;
     100 +}
     101 +```
     102 + 
     103 +The `UriBuilder` implementation in .NET uses simple string concatenation when building the `Uri` string in the last line of `GetTargetBackEndServerUrl`. For example, if the `Host` is set to `example.local/endpoint#`, then the resulting Uri from this method call might be `https://example.local:443/endpoint#/ecp/favicon.eco`. If the `Host` header contains a `:` (e.g. to change the destination port to `444`), the `UriBuilder` class assumes the host must be an IPv6 address and surrounds it with `[]`. To resolve this issue, the desired host must be prefixed with an `@` symbol, which causes the leading `[` to be treated as a username.
     104 + 
     105 +It seems likely that this vulnerability arose due to incorrect assumptions about `UriBuilder` validation.
     106 + 
     107 +**Patch analysis:**
     108 + 
     109 +The patch adds hostname validation in two locations:
     110 +```diff
     111 +--- a/Microsoft.Exchange.Data.ApplicationLogic/Exchange/Data/ApplicationLogic/Cafe/BackEndServer.cs
     112 ++++ b/Microsoft.Exchange.Data.ApplicationLogic/Exchange/Data/ApplicationLogic/Cafe/BackEndServer.cs
     113 +@@ -34,7 +34,7 @@ namespace Microsoft.Exchange.Data.ApplicationLogic.Cafe
     114 + '~'
     115 + });
     116 + int version;
     117 +- if (array.Length != 2 || !int.TryParse(array[1], out version))
     118 ++ if (array.Length != 2 || !int.TryParse(array[1], out version) || UriHostNameType.Dns != Uri.CheckHostName(array[0]))
     119 + {
     120 + throw new ArgumentException("Invalid input value", "input");
     121 + }
     122 +--- a/Exchange2013/Microsoft.Exchange.FrontEndHttpProxy/HttpProxy/ProxyRequestHandler.cs
     123 ++++ b/Exchange2013/Microsoft.Exchange.FrontEndHttpProxy/HttpProxy/ProxyRequestHandler.cs
     124 +@@ -923,7 +923,10 @@ namespace Microsoft.Exchange.HttpProxy
     125 + try
     126 + {
     127 + Uri uri = this.GetTargetBackEndServerUrl();
     128 +- bool proxyKerberosAuthentication = this.ProxyKerberosAuthentication;
     129 ++ if (!this.ProxyKerberosAuthentication && !string.Equals(uri.Host, this.AnchoredRoutingTarget.BackEndServer.Fqdn, StringComparison.OrdinalIgnoreCase))
     130 ++ {
     131 ++ throw new HttpException(503, "Service Unavailable");
     132 ++ }
     133 + bool flag2 = false;
     134 +```
     135 + 
     136 +Additionally, the patch overrides `ShouldBackendRequestBeAnonymous` in `BEResourceRequestHandler` to return true.
     137 + 
     138 +**Thoughts on how this vuln might have been found _(fuzzing, code auditing, variant analysis, etc.)_:**
     139 + 
     140 +It seems plausible that this vulnerability was found through code auditing of the frontend proxy and reviewing connections between the frontend and backend.
     141 + 
     142 +**(Historical/present/future) context of bug:**
     143 + 
     144 +In March 2021, [Microsoft published](https://www.microsoft.com/security/blog/2021/03/02/hafnium-targeting-exchange-servers/) that "multiple 0-day exploits [were] being used to attack on-premises versions of Microsoft Exchange Server in limited and targeted attacks". Microsoft credited Volexity for discovering the active exploitation and Volexity published [their analysis](https://krebsonsecurity.com/2021/03/microsoft-chinese-cyberspies-used-4-exchange-server-flaws-to-plunder-emails) on the same day.
     145 + 
     146 +## The Exploit
     147 + 
     148 +(The terms *exploit primitive*, *exploit strategy*, *exploit technique*, and *exploit flow* are [defined here](https://googleprojectzero.blogspot.com/2020/06/a-survey-of-recent-ios-kernel-exploits.html).)
     149 + 
     150 +**Exploit strategy (or strategies):**
     151 + 
     152 +The SSRF allows an attacker to submit arbitrary requests to backend `/ecp` endpoints. The frontend proxy authenticates to the backend via Kerberos as the Exchange server. However, this user is unlikely to have access provisioned for the application itself. For example, when attempting to access the DDIService via the SSRF, it responds with the error:
     153 + 
     154 +```
     155 +The user "XYZ" isn't assigned to any management roles.
     156 +```
     157 + 
     158 +As a result, an authentication bypass is also needed to make use of this vulnerability. The ECP backend exposes an endpoint that is used for authentication between proxied components. The `/ecp/proxyLogon.ecp` endpoint uses request headers and a serialized XML request body to initialize an `EcpIdentity` within the `Microsoft.Exchange.Management.ControlPanel.RbacSettings` class. If a valid user SID is provided, it creates this identity and sets the `ASP.NET_SessionId` and `msExchEcpCanary` cookies needed to authenticate to `/ecp`. An example request is to `/ecp/proxyLogon.ecp` via the SSRF is shown below:
     159 + 
     160 +```
     161 +POST /ecp/favicon.ico HTTP/1.1
     162 +Host: example.local
     163 +Cookie: [email protected]:444/ecp/proxyLogon.ecp#~1941962753;
     164 +msExchLogonMailbox: S-1-5-21-1234567890-123456789-1234567890-500
     165 + 
     166 +<r at="" ln=""><s>S-1-5-21-1234567890-123456789-1234567890-500</s></r>
     167 +```
     168 + 
     169 +```
     170 +HTTP/1.1 241
     171 +Cache-Control: private
     172 +Server: Microsoft-IIS/8.0
     173 +request-id: 00000000-0000-0000-0000-000000000000
     174 +X-CalculatedBETarget: example.local
     175 +X-Content-Type-Options: nosniff
     176 +X-DiagInfo: example
     177 +X-BEServer: example
     178 +X-FEServer: example
     179 +Set-Cookie: ASP.NET_SessionId=11111111-1111-1111-1111-111111111111; path=/; HttpOnly
     180 +Set-Cookie: msExchEcpCanary=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx; path=/ecp
     181 +Content-Length: 0
     182 +```
     183 + 
     184 +**Exploit flow:**
     185 + 
     186 +The active exploitation in the wild used this SSRF as the starting point for a full remote code execution chain against Microsoft Exchange. The general exploit flow is as follows:
     187 + 
     188 +* Leak the backend hostname
     189 +* Leak a user SID
     190 +* Authenticate with proxyLogon via SSRF (CVE-2021-26855)
     191 +* Use one of three remote code execution vulnerabilities via SSRF (CVE-2021-26857, CVE-2021-26858, or CVE-2021-27065)
     192 + * *As an example, CVE-2021-27065 has the following flow (all via SSRF):*
     193 + * List OABVirtualDirectory objects via the DDIService
     194 + * Modify the OABVirtualDirectory to inject ASP code into the ExternalUrl (typically a webshell)
     195 + * "Reset" the OABVirtualDirectory, which writes all properties to disk at a user-controlled path
     196 + * Access this webshell externally (optionally using the SSRF)
     197 + 
     198 +**Known cases of the same exploit flow:**
     199 + 
     200 +* There have been other authenticated remote code execution gadgets within Exchange, such as [CVE-2020-16875](https://msrc.microsoft.com/update-guide/vulnerability/CVE-2020-16875) and its bypass [CVE-2020-171324](https://msrc.microsoft.com/update-guide/vulnerability/CVE-2020-17132).
     201 +* The authentication bypass via proxyLogon appears to be unknown prior to these exploits.
     202 + 
     203 +**Part of an exploit chain?** This vulnerability was used as part of the observed HAFNIUM exploitation as [described by Microsoft](https://www.microsoft.com/security/blog/2021/03/02/hafnium-targeting-exchange-servers/).
     204 + 
     205 +## The Next Steps
     206 + 
     207 +### Variant analysis
     208 + 
     209 +**Areas/approach for variant analysis (and why):**
     210 + 
     211 +* Audit overrides of `GetTargetBackEndServerUrl` for similar mistakes in URI routing. Several request handlers override this method.
     212 + 
     213 +**Found variants:** N/A
     214 + 
     215 +### Structural improvements
     216 + 
     217 +What are structural improvements such as ways to kill the bug class, prevent the introduction of this vulnerability, mitigate the exploit flow, make this type of vulnerability harder to exploit, etc.?
     218 + 
     219 +**Ideas to kill the bug class:**
     220 + 
     221 +**Ideas to mitigate the exploit flow:**
     222 + 
     223 +**Other potential improvements:**
     224 + 
     225 +### 0-day detection methods
     226 + 
     227 +What are potential detection methods for similar 0-days? Meaning are there any ideas of how this exploit or similar exploits could be detected **as a 0-day**?
     228 + 
     229 +## Other References
     230 + 
     231 +* March 2, 2021: [HAFNIUM targeting Exchange Servers with 0-day exploits](https://www.microsoft.com/security/blog/2021/03/02/hafnium-targeting-exchange-servers/) by Microsoft. This post was the initial public disclosure of in-the-wild exploitation.
     232 +* March 2, 2021: [Operation Exchange Marauder: Active Exploitation of Multiple Zero-Day Microsoft Exchange Vulnerabilities](https://www.volexity.com/blog/2021/03/02/active-exploitation-of-microsoft-exchange-zero-day-vulnerabilities/) by Volexity. This post was released concurrently with the Microsoft disclosure.
     233 +* March 5, 2021: [Proxylogon](https://proxylogon.com/) by DEVCORE, the team who reported the vulnerability to Microsoft.
     234 +* March 9, 2021: [Reproducing the Microsoft Exchange Proxylogon Exploit Chain](https://www.praetorian.com/blog/reproducing-proxylogon-exploit/) by the authors of this RCA describing the process for reproducing this exploit chain using publicly available information.
     235 + 
Please wait...
Page is in error, reload to recover