Microsoft Exchange Server Remote Code Execution

Introduction

This is possible because all Exchange
servers use the same static key to encrypt/decrypt ViewState. Attackers can
specify arbitrary values for the ViewState and leverage an insecure deserialization
vulnerability to execute commands.

Why is this really bad?

The only thing you need to exploit the
vulnerability is a valid username and password for an account with a mailbox on
the on-prem Exchange. If you only have on-prem Exchange (no Office 365), then
all your user accounts can be used; the attacker only needs one. This can be
obtained with password spraying, or phishing.

Even in hybrid environments, there are
often old shared mailboxes still laying around on the on-prem Exchange, with
simple passwords.

There are open source tools that, given a
target organization name, scrape LinkedIn and other social media sites to build
a list of valid users, then start hammering the Exchange server with logon
attempts.

It’s also extremely easy to buy stolen/phished
credentials on the dark web, and the amount of self-spreading phishing
campaigns is extremely high these days (we get multiple incident response calls
every day related to compromised mailboxes…).

All of this, combined with the fact that Exchange
servers are usually Internet-facing, is devastating.

Imagine the threat actor takes over the
Exchange server. What’s next? Dumping credentials, of course. You run Mimikatz
on the Exchange server and you end up with the credentials of all authenticated
users syncing their mailbox. Most likely some of these users are admins to at
least some servers. And from Exchange, you can probably reach some of those
internal servers. Well… I don’t think I need to continue explaining at this
point. They will be domain admin pretty soon.

Additionally, there
are often direct ways
to escalate from the Exchange computer account to
domain admin.

How does the exploit work?

To exploit the vulnerability, the attacker
needs to:

  • Logon with a valid account
  • Grab the value of the session
    ID (ASP.NET_SessionId)
  • Grab the value of the ViewState
    generator (__VIEWSTATEGENERATOR)
  • Use the collected values,
    together with the known static encryption key, to create a payload exploiting
    the insecure deserialization in ViewState. For example, use YSoSerial.Net.
  • Send the malicious ViewState to
    the server

The video below demonstrates the exploit.

This video demonstrates exploiting the vulnerability using a valid low-privileged user to obtain a reverse shell running with SYSTEM privileges and extract all application keys.

The patch

The patch from February 11, 2020, fixes the problem by configuring the application to use auto-generated keys.

This is the configuration before the patch:

Figure 1 – Machine key configuration before patch

And this is how it looks like after the
patch is installed:

Figure 2 – Machine key configuration after patch

Running the same exploit after the patch is
installed will fail.

However, there is a small twist. By doing a
thorough analysis of the different keys before and after the patch was
installed, we noticed that not all keys are refreshed.

This is a dump of the keys under the ECP application before the patch:

Figure 3 – Keys before patch

And this is after the patch:

Figure 4 – Keys after patch

Although unique per installation, the keys
used for ASP.NET 4.0 and below are not regenerated with the patch. Testing on a
Windows Server 2019 with Exchange Server 2019 CU4, these are the keys used by
the application after the patch is applied.

Figure 5 – Application pools

If an attacker has dumped these keys, the
deserialization vulnerability can be re-exploited even after the patch has been
installed. This would be a sneaky way to maintain access after the patch.

The re-exploitation of a fully patched
system using the previously extracted keys is demonstrated in our video below.

Demo

This video demonstrates exploiting the
vulnerability using a valid low-privileged user to obtain a reverse shell
running with SYSTEM privileges and extract all application keys. We then
proceed to install the patch. After patching, we re-exploit the vulnerability
using one of the previously extracted keys.

This video demonstrates exploiting the vulnerability using a valid low-privileged user to obtain a reverse shell running with SYSTEM privileges and extract all application keys.

What do to next

  1. Patch ASAP!
  2. Check if you were breached
    1. IIS logs
    2. Exchange application logs
    3. Windows Event Logs
    4. Process creation logs
  3. Conduct a thorough investigation, and keep in mind that old keys can be reused after patching!
  4. If unsure, reinstall.
  5. If you revert to a backup of the application, keep in mind that web.config.backup holds the old static key!
  6. If you made any changes to the default configuration, make sure that the old static key is not used anywhere after the patch.

Want to learn more?

Fabio is speaking at Truesecs’ upcoming two-day event Cyber Security Summit 2020. A great time to ask him more questions about this or other findings!