flawopen.com/Небезопасная десериализация/Безопасность BinaryFormatter в .NET
Безопасен ли BinaryFormatter в .NET?
Microsoft считает BinaryFormatter небезопасным и указывает, что сделать его безопасным нельзя. Она рекомендует прекратить его использование, даже если приложение считает данные доверенными. В .NET 9 типы API остаются, но встроенная реализация всегда вызывает PlatformNotSupportedException; старые среды выполнения и неподдерживаемый пакет совместимости сохраняют исходный риск.
// Не десериализуйте данные через границу доверия. using System.IO; using System.Runtime.Serialization.Formatters.Binary; public static class LegacyReader { public static object Deserialize(Stream input) => new BinaryFormatter().Deserialize(input); } // Удалите и эти неограниченные полиморфные сериализаторы: SoapFormatter NetDataContractSerializer LosFormatter ObjectStateFormatter // используется внутри ASP.NET ViewState // SerializationBinder не делает эти форматы безопасными.
// Форму данных задаёт код приложения. // Nullable reference types make the DTO contract explicit. #nullable enable using System; using System.IO; using System.Text.Json; public sealed record MyDto(int Id, string Name); public static class DtoReader { public static MyDto Parse(ReadOnlySpan<byte> json) { // Ограничьте размер входа и проверьте правила приложения. if (json.Length > 65_536) throw new InvalidDataException(); MyDto? value = JsonSerializer.Deserialize<MyDto>(json); if (value is null || value.Id <= 0 || string.IsNullOrWhiteSpace(value.Name) || value.Name.Length > 100) throw new InvalidDataException(); return value; } } // Для старых NRBF-файлов изучите записи через NrbfDecoder // и перенесите разрешённые значения в DTO. // Не создавайте произвольные типы runtime.
Почему BinaryFormatter опасен
BinaryFormatter.Deserialize восстанавливает граф объектов из потока и позволяет данным, контролируемым атакующим, влиять на поток выполнения. Microsoft предупреждает о риске отказа в обслуживании, раскрытия информации и удалённого выполнения кода. Основная проблема — неограниченная полиморфная десериализация: сериализованные данные могут влиять на обрабатываемые типы и состояние объектов. Параметр форматтера не превращает API в безопасный анализатор недоверенных байтов.
Риск не ограничивается общедоступными HTTP-точками. Файлы, кэш, очереди, записи базы данных, сообщения настольных клиентов и синхронизируемое облако состояние позднее могут контролироваться атакующим. Проследите путь байтов в системе: пометки «мы это записали» или «это внутреннее» не являются постоянной гарантией доверия.
Почему SerializationBinder не решает проблему
Собственный SerializationBinder может ограничить типы, которые форматтер пытается разрешить, но Microsoft прямо заявляет: binder и другие настройки не устраняют отказ в обслуживании и могут быть недостаточны против других атак. Binder не заменяет миграцию; не принимайте недоверенные данные, пока удаляете BinaryFormatter.
Найдите старые вызовы и связанные пути
Ищите в исходниках, зависимостях проектов и настройках runtime: BinaryFormatter, IFormatter, SoapFormatter, NetDataContractSerializer, LosFormatter и ObjectStateFormatter. Проверьте поставщики состояния сеанса, адаптеры кэша, обработчики очередей, импорт/экспорт файлов и старые приложения ASP.NET Web Forms. ViewState обычно защищён кодом аутентификации сообщения (MAC); сохраняйте эту защиту и защищайте machine key. MAC не делает универсальную десериализацию BinaryFormatter безопасной.
Планируйте миграцию по формату данных и версии runtime
Для новых данных выберите явный контракт, например System.Text.Json, DataContractSerializer, MessagePack или protobuf-net, с учётом формата и совместимости; прямой замены нет. Для сохранения старых NRBF-файлов NrbfDecoder из .NET 9 может декодировать записи без создания закодированных типов приложения. Проверьте структуру и переносите только ожидаемые значения в DTO. Отдельно изучите рекомендации по миграции ресурсов, буфера обмена и drag-and-drop WinForms/WPF.
Частые вопросы
Microsoft рекомендует миграцию даже при кажущихся доверенными данных: хранилища, кэш, файлы, синхронизация и нижестоящие службы пересекают границы доверия. Определите, кто может записывать данные в каждый источник, и удалите BinaryFormatter вместо опоры на предположение.
В .NET 9 типы API остаются, но встроенная реализация всегда вызывает PlatformNotSupportedException, независимо от прежнего флага совместимости. Проверьте вызовы и мигрируйте до обновления. Неподдерживаемый пакет совместимости возвращает уязвимую реализацию, но не исправляет безопасность.
По умолчанию Json.NET задаёт TypeNameHandling как None, поэтому метаданные payload не выбирают произвольные CLR-типы. Не включайте другие значения для недоверенных данных. Если нужна полиморфность, используйте строгий allowlist под контролем приложения и следуйте документации библиотеки. См. Безопасен ли TypeNameHandling?
Источники и ссылки
- Microsoft Learn — BinaryFormatter security guide
- Microsoft Learn — BinaryFormatter migration guide
- Microsoft Learn — Choose a BinaryFormatter replacement
- Microsoft Learn — Safely read NRBF payloads with NrbfDecoder
- Microsoft Learn — SYSLIB0011
- Microsoft Learn — ASP.NET ViewState MAC
- CWE-502 — Deserialization of Untrusted Data
- Is Json.NET TypeNameHandling safe?