Microsoft Exchange Server Remote Code Execution

Introduction

On February 11th, Microsoft released a patch for Microsoft Exchange Server (all versions), addressing a serious vulnerability allowing any authenticated user to execute arbitrary commands with SYSTEM privileges. The vulnerability was given CVE number CVE-2020-0688.

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.

The patch

The patch from February 11th 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!


By Fabio Viggiani

Fabio is the technical lead of Truesec Security Team. He leads advanced Incident Response missions, and has extensive experience in Red Team assignments as well as traditional penetration tests.

He also works closely with Truesec Security Operations Center, focusing on Threat Hunting and detection.

This gives him a strong insight in the current threat landscape and the latest attacks and detection techniques.