Hunting and Responding to ProxyShell Attacks

ProxyShell is an attack chain that exploits three known vulnerabilities in On-Premises Exchange servers: CVE-2021-34473, CVE-2021-34523 and CVE-2021-31207. ProxyShell allows a remote unauthenticated attacker to execute arbitrary commands on an unpatched Exchange Server through port 443. The bug relies in the Client Access Service (CAS) component in Exchange and was discovered by a security researcher in 2021. The presentation of the security researcher can be found here:

To summarize those exploits:

  • CVE-2021-34473: Allows arbitrary backend URL access as the Exchange machine account (NT AUTHORITY\SYSTEM)
  • CVE-2021-34523: Elevation of Privileges to gain access to the Exchange PowerShell backend to run PowerShell commands
  • CVE-2021-31207: This vulnerability leverages the New-MailboxExportRequest cmdlet in order to export the user mailbox to an arbitrary file location, which can be used to write a Webshell on the Exchange server.

During this blog post, we will be demonstrating this attack, show how we can hunt for the artifacts, and more importantly. What can we do about it to mitigate the problem?

ProxyShell Attack

At this example, we have the user ‘Jones’. This is just a regular Domain User and has no special privileges within AD or on the Exchange servers.

This user can run a simple LDAP query to enumerate all the Exchange servers within Active Directory.

dsquery * "cn=Configuration,dc=contoso,dc=com" -Filter "(objectCategory=msExchExchangeServer)"

At this example, we have two Exchange servers in the domain. Both of these Exchange servers are unpatched.

Let’s start with targeting an Exchange server via the ProxyShell vulnerability. To quickly summarize what we’re seeing in this console. With a known e-mail address, we are able to send an Autodiscover request to enumerate the LegacyDN of a user. This is an attribute in AD that identifies a mailbox by its distinguished name. By obtaining the LegacyDN, we can use it to send a MAPI request to get the SID of the user. With the SID and e-mail that we obtained, we can construct a valid authentication token and use this to authenticate against the backend of Exchange PowerShell to run commands.

We can now run PowerShell commands like an Exchange Admin would do in Exchange Management Shell. Here is an example where we are initiating a new role assignment to a user. This role allows a user to export mailboxes.

At this example, we are exporting a mailbox of a user.

This attack would not work if we were not able to retrieve a valid account with a mailbox attached to it.

Another example we can do is using the New-MailboxExportRequest cmdlet in order to export the user mailbox to an arbitrary file location, which then can be used to write a Webshell on the Exchange server. This can be achieved by leveraging CVE-2021-31207 and is part of the overall ProxyShell vulnerability.

As we can see here, we are now running as NT AUTHORITY\SYSTEM on an unpatched Exchange server.

At this example, we are enumerating all the Domain Controllers via nltest through our Webshell.

We can basically run every command we’d like, so in this example. I’m using bitsadmin.exe to download SharpHound and drop it on disk.

To finalize this example, we are executing SharpHound through our Webshell that we were able to implant via the ProxyShell vulnerability.

ProxyShell as initial access

The DFIR Report observed at the end of December 2021 that APT35 was using ProxyShell to gain initial access to an environment and execute code via multiple Webshells.


A great example how initial access was gained could be via a public facing OWA. As we can see in this example. Here is an OWA that has been exposed to the internet. If this server was not patched, it could easily be exploited by anyone with internet access.

At this example, we can see that the server is unpatched which allows an attacker to exploit this ProxyShell vulnerability to obtain initial access to the environment.

Here we can see how an attacker exploited this server to obtain NT AUTHORITY\SYSTEM on this Exchange server.

To finalize it, we can see the evidence of the Webshell being dropped successfully.

Investigating ProxyShell in the logs

This section will cover the different artifacts on an On-Premises Exchange server that we can take a look at to hunt for this activity.

IIS logs

IIS logs provide great visibility in all the GET and POST requests that are made to the Exchange server. IIS logs are stored by default at the following location: C:\inetpub\logs\LogFiles

When hunting for ProxyShell, we can start looking at the IIS logs to see if we can find any suspicious POST requests that contains autodiscover.json and PowerShell?X-Rps-CAT. Here is a snippet of a ProxyShell activity in the IIS logs:

2022-10-17 19:18:45 POST /autodiscover/autodiscover.json<empty>;&cafeReqId=92a03e8b-530a-4f88-b38e-84bdbfac137c; 443 - Python+PSRP+Client - 200 0 0 10

Exchange has a PowerShell remoting feature that can be used to read and send e-mails. This feature cannot be used by the SYSTEM account, since it doesn’t have a Mailbox attached to it. However, because the attacker can access the Exchange PowerShell backend directly. It can specify an arbitrary value in X-Rps-CAT to impersonate any user. This is used to downgrade from the SYSTEM account to an Exchange Admin. In order to run PowerShell commands as that Exchange Admin.

Let’s try this one more time together, so we are going to execute this attack. I’m going to impersonate the user ‘Cena’ and run a command in Exchange PowerShell to retrieve all the Exchange servers.

As you can see, it will throw an error and tell me that ‘Get-ExchangeServer’ cmdlet is not recognized. This is because ‘Cena’ is just a regular user and doesn’t have any privileges in Exchange.

Let’s now impersonate an Exchange Admin and run the exact same command:

At the result, we can see that it returned two Exchange servers.

Let’s look at the results one more time to see what we can see in the IIS logs and as expected. The results are the same as the above one. As we can see in the POST request, there is an arbitrary value that is specified in the X-Rps-CAT parameter that allows an attacker to impersonate any user, like we just did. This is a good indicator to detect ProxyShell.

2022-10-17 20:00:03 POST /autodiscover/autodiscover.json a=devkm@iewrz.uer/powershell/?X-Rps-CAT=VgEAVAdXaW5kb3dzQwBBCEtlcmJlcm9zTBNUZXN0aW5nQGNvbnRvc28uY29tVS1TLTEtNS0yMS0zNDYwMzE4NTAwLTM2MDg3MzE5NzAtMjk0NzE3NDA1MS01MDBHAQAAAAcAAAAMUy0xLTUtMzItNTQ0RQAAAAA=&CorrelationID=<empty>;&cafeReqId=f53e94a1-29f2-4772-9c84-0fc218d2a6eb; 443 - python-urllib3/1.26.12 - 200 0 0 211

Autodiscover Request logs

Autodiscover logs are part of the HttpProxy logs and contains all the requests that have been made and can add extra insights as well that can be used alongside the IIS logs. In my opinion, IIS logs should already be enough. However, it never hurts to have more data to proof evidence. Autodiscover logs are stored at the following location: C:\Program Files\Microsoft\Exchange Server\V15\Logging\HttpProxy\Autodiscover

This is how it looks like:

Here is a snippet of how a request looks in the Autodiscover logs:

2022-10-17T20:00:03.023Z,2ee079e4-d93f-4713-b742-82af67f1e125,15,1,1531,12,,Autodiscover,,/autodiscover/autodiscover.json,,,false,,,Anonymous~Anonymous,python-urllib3/1.26.12,,EXCHANGE2016,200,200,,POST,Proxy,,15.01.1531.000,IntraForest,AnonymousRequest-RandomBackEnd,,,,2887,1642,,,0,23,,0,22;,22,,0,22,,0,36,0,0,1,0,10,0,0,0,0,0,35,1,10,25,26,26,36,,?a=devkm@iewrz.uer/powershell/?X-Rps-CAT=VgEAVAdXaW5kb3dzQwBBCEtlcmJlcm9zTBNUZXN0aW5nQGNvbnRvc28uY29tVS1TLTEtNS0yMS0zNDYwMzE4NTAwLTM2MDg3MzE5NzAtMjk0NzE3NDA1MS01MDBHAQAAAAcAAAAMUy0xLTUtMzItNTQ0RQAAAAA=,,BeginRequest=2022-10-17T20:00:02.987Z;CorrelationID=<empty>;ProxyState-Run=None;;FEAuth=BEVersion-1942062587;BeginGetRequestStream=2022-10-17T20:00:03.012Z;OnRequestStreamReady=2022-10-17T20:00:03.012Z;BeginGetResponse=2022-10-17T20:00:03.012Z;OnResponseReady=2022-10-17T20:00:03.022Z;EndGetResponse=2022-10-17T20:00:03.022Z;ProxyState-Complete=ProxyResponseData;SharedCacheGuard=0;EndRequest=2022-10-17T20:00:03.023Z;S:ServiceLatencyMetadata.AuthModuleLatency=0;I32:ADS.C[DC]=1;F:ADS.AL[DC]=21.8654,RetryInternalBeginCalculateTargetBackEnd=AnchorMailbox:Smtp~autodiscover/autodiscover.json?a devkm@iewrz.uer RoutingHint:ExplicitLogon-SMTP-NoUser ;,,,,,CafeV1

MSExchange CmdletLogs

MSExchange Management logs provide all the Exchange Management Shell commands that were ran on a machine. As we know from CVE-2021-31207. It is using the New-MailboxExportRequest cmdlet in order to export the user mailbox to an arbitrary file location, which then can be used to write a Webshell on the Exchange server.

This is an example on how it may look like:

When we are seeing the New-MailboxExportRequest cmdlet being called and containing a suspicious file specified at the -FilePath parameter and it is NOT a .pst extension. This is a great indicator that someone was attempting to drop a Webshell.

At this example, we can see the user Testing being specified in the event log. The Webshell is imported as an e-mail inside the user ‘Testing’ mailbox at the draft folder. It is then exported to C:\inetpub\wwwroot\aspnet_client

This is how it looks like:

Let’s now take a closer look at the event log itself:

Cmdlet suceeded. Cmdlet New-MailboxExportRequest, parameters -Mailbox "Testing" -Name "bddd915f80de4342a9ff3e3c1665d53a" -ContentFilter "Subject -eq 'bddd915f80de4342a9ff3e3c1665d53a'" -FilePath "\\\c$\inetpub\wwwroot\aspnet_client\piyhok.aspx".

We can see in the Inbox folder of the user Testing to see if have an e-mail that contains this subject. bddd915f80de4342a9ff3e3c1665d53a. If that’s the case, we can view the e-mail header which allows us to pivot further to see where this request was coming from. At this example, we can see that this ProxyShell attack was initiated from

Hunting for Webshells attempts

During ProxyShell attacks, it is usually the case that an attacker is dropping a Webshell to remain persistent. Here we can see a Webshell that was dropped via ProxyShell:

We can look in the IIS logs to see whether this request was successful or not. This is a snippet of how the request would have look like:

2022-10-17 15:21:14 POST /aspnet_client/piyhok.aspx - 443 - Mozilla/5.0+(Windows+NT+10.0;+WOW64)+AppleWebKit/537.36+(KHTML,+like+Gecko)+Chrome/92.0.4515.131+Safari/537.36. - 200 0 0 5423

How can we stop ProxyShell?

Let’s understand which Exchange versions are affected for this ProxyShell vulnerability. Good thing to keep in mind is that there are only specific security updates available for certain versions. If you haven’t installed any of these May or July 2021 security patches on your Exchange servers. You are vulnerable against ProxyShell. If you are using an Exchange version that does not has security updates available. You need to upgrade your Exchange server to the latest CU version to be protected.

Exchange 2019:

Exchange 2016:

Exchange 2013:

At this example, we have an Exchange 2016 CU20. However, as we can see in this screenshot. We are able to exploit it through the ProxyShell vulnerability.

Since we are using Exchange 2016 CU20. There are security updates available that we can install. For the purpose of this demo, we will only install the May 2021 update to demonstrate that it would prevent ProxyShell.

Applying a security update requires the server to reboot.

To verify whether the security update has been installed. Run the following command:

Get-Command Exsetup.exe | ForEach {$_.FileVersionInfo}

Now start comparing the ProductVersion with the version that we can see at the download link. If the version aligns well with each other, we have applied the patch correctly.

Did it work?

The main question that we all want to know. Did it work after the update has been applied? Short answer, yes. It does, as you can see here. We are unable to exploit the server again via the ProxyShell vulnerability.


Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s