πŸ”’
There are new articles available, click to refresh the page.
Before yesterdayZero Day Initiative - Blog

CVE-2021-26420: Remote Code Execution in SharePoint via Workflow Compilation

In June of 2021, Microsoft released a patch to correct CVE-2021-26420 – a remote code execution bug in the supported versions of Microsoft SharePoint Server. This bug was reported to the ZDI program by an anonymous researcher and is also known as ZDI-21-755. This blog takes a deeper look at the root cause of this vulnerability.

Before this patch being made available, this vulnerability could be used by an authenticated user to execute arbitrary .NET code on the server in the context and permissions of service account of SharePoint web application. For successful attack, the attacker should have β€œManage Lists” permissions on any SharePoint site. By default, any authenticated user can create their own site where they have the necessary permissions.Β Β Β 

The Vulnerability

SharePoint workflows are pre-programmed mini-applications that streamline and automate a wide variety of business processes. An organization can use workflows to attach business logic to documents or items in a SharePoint list or library.

For security purposes, Workflow Foundation (WF) on SharePoint runs workflows only when all dependent types and assemblies are authorized in the authorizedTypes list in the web.config file. Along with allowed types, this list also contains items that block specific types from allowed namespaces that are considered dangerous. One example is System.Workflow.ComponentModel.Compiler. The Compile() method offered by WorkflowCompiler compiles a workflow based on parameters. Workflows in SharePoint are normally compiled in very restricted context (no code, types restricted by the authorizedTypes list, etc.), but invoking WorkflowCompiler would allow attackers to create a new context without these restrictions by specifying appropriate parameters. Because of this, WorkflowCompiler is blocked by the authorizedTypes list in web.config:

Therefore, we cannot mount an attack using WorkflowCompiler type. However, examining the .NET code of WorkflowCompiler.Compile reveals something interesting:

From here we see that the bulk of the implementation of WorkflowCompiler.Compile resides a different class named WorkflowCompilerInternal. This class is not blocked by authorizedTypes list. Furthermore, since it is found within the `System.Workflow` namespace, it is allowed by the line:

Therefore, we can compile an arbitrary workflow by invoking the WorkflowCompilerInternal type directly.

For arbitrary code execution, we can use the following XOML file (Attck.xoml). When compiled, it will execute the desired .NET commands, provided that the noCode flag is not specified:

Here is the .rules file (WF02.rules) of a SharePoint workflow that invokes the WorkflowCompilerInternal.Compile to compile an arbitrary XOML workflow definition, provided that the XOML file can be retrieved from an SMB share:

This rule will be triggered by the following lines from the XOML file of our SharePoint workflow (WF02.xoml):

An attacker could store Attck.xoml in a shared SMB folder controlled by the attacker and upload the WF02.xoml and WF02.rules files to a location on the SharePoint site, for example, to the Documents folder. Also, the attacker would need a workflow configuration file (WF02config.xml) that points to the uploaded XOML and rules files, and associates them with the ListID of a list in the site where the attacker can add new items:

An attacker would need to associate this new workflow with the SharePoint list. This can be done by using the AssociateWorkflowMarkup method from the WebPartPages WebService (/_vti_bin/WebPartPages.asmx) and providing the relative path to the uploaded config file.

To trigger workflow execution, the attacker adds a new item to the target SharePoint list. Β 

Proof of Concept

For this demonstration, we use Microsoft SharePoint Server 2019 installed with all default options on Windows Server 2019 Datacenter. The server’s computer name is sp2019.contoso.lab and it is a member of the contoso.lab domain. The domain controller is a separate virtual machine. It has been updated to the February 2021 patch level (version 16.0.10371.20043) and a couple of users have been added, including β€œuser2” as a regular, unprivileged user.

On the attacker side, we need:
-- an SMB server hosting the Attck.xoml file containing the .NET code we want to execute. It must be hosted on a share that can be accessed by the SharePoint server
-- our PoC application for sending SOAP requests to the server (SP_soap_RCE_PoC.exe) that calls the AssociateWorkflowMarkup method of the WebPartPages web service
-- the workflow config file, WF02config.xml
-- The XOML and .rules files referenced by the workflow config file
-- any supported web browser. For this demonstration, we are using Firefox.

Achieving Remote Code Execution

Let’s visit our SharePoint Server and authenticate as a regular user. In my case it is user2:

Picture2.png

Before our attack, we need to prepare a few things. We could try to do this with current user sites, but if possible, we recommend creating a new site so that we will be the owner and have all permissions.

Click on β€œSharePoint” on the top panel:

Picture3.png

Now click the β€œ+ Create site” link:

Picture4.png

Choose Team Site.

Pick a name for the new site. Here we use testsiteofuser2.

Picture5.png

Click β€œFinish” and the new site will be created:

Picture6.png

Now we need to create a new list. Click on the β€œSite contents” link:Β 

Picture7.png

Then click β€œ+ New” -> β€œList”:

Picture8.png

Enter any available name. For example, β€œNewList”:

Picture9.png

And click β€œCreate”:

Picture10.png

We will need the ListID of this new list. Let’s go back to the β€œSite contents” page and click on β€œSettings” in the dropdown menu for our new list:

Picture11.png

We will be redirected to the listedit.aspx page:

Picture12.png

We need value of the List URL parameter. In my case it is:

28e11fd2-9f76-418c-83ea-dc0d8f3c184bΒ 

We need to place this value into the ListId attribute in the workflow config file, WF02config.txt:Β 

Picture13.png

Now we need to upload the Attck.xoml file, containing the .NET code we want to run, into an SMB folder that is accessible from the SharePoint server.

We should place the remote path to the Attck.xoml file into WF02.rules:

Picture14.png

Save changes in both files (WF02config.txt and WF02.rules) and upload them together with the WF02.xoml file to the Documents folder of our SharePoint site:

Picture15.png

We are almost ready for the final step. But first, let’s check the C:\windows\temp folder on our target SharePoint server:

Picture16.png

There is no PoC_SPRCE02.txt file yet.

For our attack, we will use the SP_soap_RCE_PoC.exe application. We need to provide the following information:

β€” BaseUrl of the target SharePoint Site (in this case http://sp2019/sites/testsiteofuser2/)Β Β 
β€” UserName (in this case user2)Β 
β€” Password
β€” Domain

β€” Relative path to the workflow config file on our site - "Shared Documents/WF02config.txt"

> SP_soap_RCE_PoC.exe http://sp2019/sites/testsiteofuser2/ user2 [email protected] contoso "Shared Documents/WF02config.xml"

Picture17.png

We received a β€œSuccess” result. Now to trigger the RCE, we just need to add a new item to NewList:Β 

Picture18.png

Click on the β€œSave” button there.

Let’s check C:\windows\temp folder on our target SharePoint server:

Picture19.png

The file PoC_SPRCE02.txt has been created, demonstrating the success of our code execution. In this manner, our attacker can execute arbitrary OS commands in the context of the SharePoint web application account.

To run additional OS commands, we would need to place them into Attck.xoml file in the shared folder and create another new item in NewList.

Picture20.png

Conclusion

Microsoft patched this in June and assigned identifier CVE-2021-26420, with a CVSS score of 7.1. While the inclusion of an attacker-controlled SMB server adds a level of complexity, this bug can still be used for code execution in many scenarios. Since SharePoint is generally considered an attractive target for attackers, it would not be surprising if this bug were to be found in the wild. SharePoint continues to be an attractive target for security researchers, and many SharePoint-related disclosures are currently in our Upcoming queue. Stay tuned to this blog for details about those bugs once they are disclosed.

Until then, follow the team for the latest in exploit techniques and security patches.

CVE-2021-26420: Remote Code Execution in SharePoint via Workflow Compilation

CVE-2021-28474: SharePoint Remote Code Execution via Server-Side Control Interpretation Conflict

In May of 2021, Microsoft released a patch to correct CVE-2021-28474, a remote code execution bug in supported versions of Microsoft SharePoint Server. This bug was reported to ZDI by an anonymous researcher and is also known as ZDI-21-574. This blog takes a deeper look at the root cause of this vulnerability.

The vulnerability allows authenticated users to execute arbitrary .NET code on the server in the context of the service account of the SharePoint web application. For a successful attack, the attacker needs SPBasePermissions.ManageLists permissions for a SharePoint site. By default, authenticated SharePoint users can create sites/subsites and will have all necessary permissions.Β Β Β 

The Vulnerability

This problem exists due to an inconsistency between code that is used for security verification and code that is used for the actual processing of user input.

Security verification is performed by EditingPageParser.VerifyControlOnSafeList(). This function verifies that the provided input does not contain unsafe controls, meaning any control that is not marked as safe by SafeControl elements in web.config file.

The EditingPageParser.ParseStringInternal() function parses user input from dscXml and populates hashtable with information from the Register directives and hashtable2 with values from the tags of server controls. In the next step, it tries to verify each element of hashtable2 against the SafeControl elements from the web.config file. If a control is not marked there as safe, it throws an exception.

Let’s take a closer look at how values in hashtable2 are populated:

As we can see, the SharePoint server verifies only server-side controls (tags with the runat="server" attribute). This is reasonable since client-side elements do not require verification.

Β If verification passes, SharePoint will process the provided markup. Let’s review the code that performs the processing:

As you can see, the steps for parsing content at processing time are very similar to the parsing steps at verification time. However, there is a critical one-line difference:

Β Β Β Β Β Β text4 = HttpUtility.HtmlDecode(text4);

At processing time, attribute values are HTML-decoded by the parser, but there is no corresponding line at verification time. This means that if we have an ASPX tag with an attribute such as runat="server", the EditingPageParser.VerifyControlOnSafeList() function will not consider it a server-side control and will not check it for safety. At processing time, however, it will be recognized and executed as a server-side control.

Exploitation

For our attack, we will use the System.Web.UI.WebControls.Xml control. It allows us to retrieve information from an arbitrary XML file. We can use this to exfiltrate the machineKey section from web.config, which we allow us to forge an arbitrary ViewState and achieve remote code execution via ViewState deserialization.

We can see that System.Web.UI.WebControls.Xml is marked as unsafe via a SafeControl element in web.config:

To deliver our payload to the server, we will use the WebPartPagesWebService.ExecuteProxyUpdates web API method that is accessible via the /_vti_bin/WebPartPages.asmx endpoint. It allows us to render ASPX markup from the OuterHtml attribute in Design mode. User input will be verified by the VerifyControlOnSafeList method.

For a successful attack, we need to provide a relative path to any existing site page:

We can use information from the machinekey section from web.config to create a valid ViewState that will be deserialized by SharePoint. This allows us to run an arbitrary OS command via deserialization of untrusted data.

Proof of Concept

For this demonstration, we use Microsoft SharePoint Server 2019 installed with all default options on Windows Server 2019 Datacenter. The server’s computer name is sp2019.contoso.lab and it is a member of the contoso.lab domain. The domain controller is a separate virtual machine. It has been updated to the January 2021 patch (version 16.0.10370.20001β€Ž) and a couple of users have been added, including β€œuser2” as a regular, unprivileged user.

On the attacker side, we need any supported web browser, our PoC application for sending SOAP requests to the server, and the ysoserial.net tool. For this demonstration, we are using Firefox as our browser.

Getting Remote Code Execution

Let’s begin by visiting our SharePoint Server and authenticating as β€œuser2”.

Picture1.png

Let’s create a site so we will be the owner and have all permissions.

Click on β€œSharePoint” on the top panel:

Picture2.png

Now click β€œ+ Create site” link:

Picture3.png

Choose Team Site.

Now we need to pick a name for the new site. In this case, we use ts01.

Picture4.png

Click β€œFinish” and the new site will be created:

Picture5.png

Now we need a relative path to any site page in this site. We can see list of pages by going to /SitePages/Forms/ByAuthor.aspx:

Picture6.png

We can click on the desired page and take the relative path from the address bar (note that we omit the leading site name and β€œ/” ) :

Picture7.png

In our case, it is SitePages/Home.aspx.

Now we use our custom executable to send a request to the server that triggers the vulnerability. We need to provide the URL to our site, credentials, and the relative path determined above. In this case:

Β Β Β Β Β Β >SP_soap_RCE_PoC.exe http://sp2019/sites/ts01/ user2 [email protected] contoso "SitePages/Home.aspx"

Picture8.png

If our attack is successful, we receive the content of web.config:

Picture9.png

Within the file, we search for the machineKey element:

Picture10.png

For our RCE attack, we need the value of validationKey. In this case it is:

Β Β Β Β Β Β validationKey=”FAB45BC67E06323C48951DA2AEAF077D8786291E2748330F03B6601F09523B79”

We can also see the algorithm: validation="HMACSHA256".

Using this information, we can perform our remote code execution attack. Before the final step, let’s go to the target SharePoint server and open C:\windows\temp folder:

Picture11.png

We verify there is no SP_RCE_01.txt file yet.

Now let’s go back to the β€œattacker” machine, and open the Success.aspx page on our site:

In this case, the URL is http://sp2019/sites/ts01/_layouts/15/success.aspx:

Picture12.png

Now we need to open the source code view for this page and find the value of __VIEWSTATEGENERATOR:

Picture13.png

In this example, it is AF878507.

We now have all the data needed to forge an arbitrary ViewState:

Β __VIEWSTATEGENERATOR=AF878507

validationKey=FAB45BC67E06323C48951DA2AEAF077D8786291E2748330F03B6601F09523B79

validationAlg=HMACSHA256

We generate the ViewState using ysoserial, as follows:

>ysoserial.exe -p ViewState -g TypeConfuseDelegate -c "echo RCE > c:/windows/temp/SP_RCE_01.txt" --generator="AF878507" --validationkey="FAB45BC67E06323C48951DA2AEAF077D8786291E2748330F03B6601F09523B79" --validationalg="HMACSHA256" --islegacy --minify

Picture14.png

Here is the resulting payload:

We need to URL-encode it and send it as the __VIEWSTATE parameter in the query string in a request to our server:

We paste this URL into the browser. The response appears as an error:

Picture15.png

Nevertheless, when we check the C:\windows\temp folder on our target server again:

Picture16.png

Our target file was successfully created, demonstrating that we achieved code execution. In the same way, an attacker can execute any OS command in the context of the SharePoint web application.

Conclusion

Microsoft patched this in May and assigned identifier CVE-2021-28474, with a CVSS score of 8.8. SharePoint continues to be an attractive target for researchers and attackers alike, and several SharePoint-related disclosures are currently in our Upcoming queue. Stay tuned to this blog for details about those bugs once they are disclosed.

Until then, follow the team for the latest in exploit techniques and security patches.

CVE-2021-28474: SharePoint Remote Code Execution via Server-Side Control Interpretation Conflict

CVE-2021-31181: Microsoft SharePoint WebPart Interpretation Conflict Remote Code Execution Vulnerability

In May of 2021, Microsoft released a patch to correct CVE-2021-31181 – a remote code execution bug in the supported versions of Microsoft SharePoint Server. This bug was reported to the ZDI program by an anonymous researcher and is also known as ZDI-21-573. This blog takes a deeper look at the root cause of this vulnerability.

Before this patch being made available, this vulnerability could be used by an authenticated user to execute arbitrary code on the server in the context of the service account of the SharePoint web application. For a successful attack, the attacker must have SPBasePermissions.ManageLists permissions on any SharePoint site. By default, any authenticated user can create their own site where they have the necessary permission.Β Β Β 

The Vulnerability

This attack is possible due to insufficient validation of user input in the EditingPageParser.VerifyControlOnSafeList() method. This method verifies user input against a list of unsafe controls and should raise an exception if any control is not marked as safe by the SafeControl elements as specified in web.config.

A good example of an unsafe control that is forbidden by SharePoint is System.Web.UI.WebControls.XmlDataSource. This control is dangerous because it would allow an attacker to get information from an arbitrary XML file on the server. As we will see, this could be used not only for information disclosure but even for code execution.

We can see that it is marked as unsafe via a SafeControl element in web.config:

Because of this, an attacker should not be able to instantiate this control. However, we will see how we can bypass verification in EditingPageParser.VerifyControlOnSafeList().

EditingPageParser.ParseStringInternal() parses user input (dscXml) and populates hashtable with information from Register directives and hashtable2 with values from tags that represent server controls. In the next step, it tries to create a Type object for each element from hashtable2 and checks it against an allowed list of SafeControls. However, it will ignore the tag of the server control if the Type cannot be resolved. Normally, this would not create a hazard. If a Type cannot be resolved at the verification stage, then it should similarly fail to resolve later during the actual processing of markup. However, an inconsistency between the code in EditingPageParser and TemplateParser breaks this assumption.

Let’s look closer at how the values in hashtable are populated, and let’s pay attention to the namespace attribute of the Register directive:

The value of the namespace attribute will be stored in triplet.First. Let’s suppose that we have Namespace="System.Web.UI.WebControls " (note the trailing space) in our Register directive, and a tag named XmlDataSource. As you can see, there are no Trim() calls for the namespace attribute. Due to the trailing space, VerifyControlOnSafeList will not be able to resolve the Type System.Web.UI.WebControls .XmlDataSource and consequently it will not be blocked. Later, though, during actual processing of the Register directive, the following code executes:

At this stage, the Namespace will be trimmed and a Type for System.Web.UI.WebControls.XmlDataSource will be successfully resolved. This means the unsafe control will be processed by the server.

For our attack, we will use the WebPartPagesWebService.RenderWebPartForEdit webapi method. It is accessible via the /_vti_bin/WebPartPages.asmx endpoint. It takes ASPX markup as an input, verifies it using EditingPageParser.VerifyControlOnSafeList, and, if there are no unsafe elements, processes the markup in Design mode. The resulting HTML will be returned to the web client.

We will use the WebPart Microsoft.SharePoint.WebPartPage.XsltListFormWebPart with our unsafe XmlDataSource, specifying a simple XSL transformation to copy the result verbatim to our output. In this way we can obtain the contents of an arbitrary XML file from the server. We choose to disclose the contents of web.config. This will provide us with the validation key needed to forge a VIEWSTATE parameter, providing a path to remote code execution.

To proceed, we will also need to provide the Title of any existing SPList from the current site, as well as the site’s webID. These can be obtained easily. We will see how to do this in the PoC section.

Here is an example of a RenderWebPartForEdit request:

We can use the machinekey section from web.config to create a valid VIEWSTATE parameter that causes an arbitrary OS command to be executed when the ViewState is deserialized on the server.

Proof of Concept

For this demonstration, we use Microsoft SharePoint Server 2019 installed with all default options on Windows Server 2019 Datacenter. The server’s computer name is sp2019.contoso.lab and it is a member of the contoso.lab domain. The domain controller is a separate virtual machine. It has been updated to January 2021 Patch (Version 16.0.10370.20001β€Ž) and a couple of users have been added, including β€œuser2” as a regular, unprivileged user.

On the attacker side, we need any supported Web Browser, our PoC application for sending SOAP requests to the server, and the ysoserial.net tool. For this demonstration, we are using Firefox as our browser.

Getting Remote Code Execution

Let’s begin by visiting our SharePoint Server and authenticating as β€œuser2”.

Picture1.png

Let’s create a site so that we will be the owner and have all permissions.

Click on β€œSharePoint” on the top panel:

Picture2.png

Now click the β€œ+ Create Site” link:

Picture3.png

Choose Team Site.

Choose a name for the new site. In this example, it is ts01.

Picture4.png

Click β€œFinish” and the new site will be created:

Picture5.png

Now let’s get the webId for the site. This can be done with a request to /_api/web/id :

Picture6.png

In this example, it is 6e7040c8-0338-4448-914d-a7061e0fc347.

We also need the title of any existing SPlist in the current site. The β€œDocuments” SPlist is available on most sites, but we can use any item from the /_layouts/15/viewlsts.aspx page:

Picture7.png

Now we use our PoC to send a request to the server. We need to provide the base URL for our site, valid user credentials, the title of an SPList, and the webId. In our case:

>PoC.exe http://sp2019/sites/ts01/ user2 [email protected] contoso "Documents" "{6e7040c8-0338-4448-914d-a7061e0fc347}"

If this step successful, we will get the machineKey section of web.config:

Picture9.png

For our RCE attack, we need the value of validationKey. In this example it is:

validationKey=”FAB45BC67E06323C48951DA2AEAF077D8786291E2748330F03B6601F09523B79”

We can also see the algorithm: validation="HMACSHA256"

Using this information, we can proceed to get remote code execution. Before the actual attack, let’s go to the target SharePoint Server and open C:\windows\temp folder:

Picture10.png

Note that there is no PoC_SPRCE01.txt file yet.

Now let’s go back to the attacker machine. We need to collect one more piece of information, which is the value of __VIEWSTATEGENERATOR. We can get this by browsing to the success.aspx page on our site. In this example, the URL is http://sp2019/sites/ts01/_layouts/15/success.aspx:

Picture11.png

Viewing the source code, we can find the value of __VIEWSTATEGENERATOR:

Picture12.png

In this example it is AF878507.

In summary, the values needed to forge a VIEWSTATE are as follows:

__VIEWSTATEGENERATOR=AF878507 validationKey=FAB45BC67E06323C48951DA2AEAF077D8786291E2748330F03B6601F09523B79 validationAlg=HMACSHA256

We provide these values on the command line of ysoserial, as follows:

>ysoserial.exe -p ViewState -g TypeConfuseDelegate -c "echo RCE > c:/windows/temp/PoC_SPRCE01.txt" --generator="AF878507" --validationkey="FAB45BC67E06323C48951DA2AEAF077D8786291E2748330F03B6601F09523B79" --validationalg="HMACSHA256" --islegacy --minify

Picture13.png

The result is a valid VIEWSTATE.

We need to URL-encode this ViewState and send it as a __VIEWSTATE parameter to our server. For example, this can be done by composing a URL with a __VIEWSTATE query string parameter, as follows:

Browsing to this URL, an error page is returned.

Picture14.png

However, when we check the C:\Windows\temp folder on the SharePoint server:

Picture15.png

Our target file was successfully created, demonstrating that we achieved code execution. In the same way, an attacker can execute any OS command in the context of the SharePoint web application.

Conclusion

Microsoft patched this in May and assigned identifier CVE-2021-31181, with a CVSS score of 8.8. SharePoint continues to be an attractive target for researchers and attackers alike, and several SharePoint-related disclosures are currently in our Upcoming queue. Stay tuned to this blog for details about those bugs once they are disclosed.

Until then, follow the team for the latest in exploit techniques and security patches.

CVE-2021-31181: Microsoft SharePoint WebPart Interpretation Conflict Remote Code Execution Vulnerability

  • There are no more articles
❌