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!


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!


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


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 ¯_(ツ)_ /¯


An example in ZDI’s blog post:


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:


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


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


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


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


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


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:


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



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:


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


Full stacktrace:

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


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:




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


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):


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


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!):


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!


  • 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:

Host: sharepoint
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0
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:


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;
            var base64String = Convert.ToBase64String(ms.ToArray());

(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:


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:



Here is the Step by step demo of the PoC:

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