
.NET 7 форк seal-security-nuget-demo: та же история эксплуатации CVE-2024-21907, переориентированная на клиентов, привязанных к .NET SDK 7.
Это переориентированный форк канонического seal-security-nuget-demo (который нацелен на net9.0). История эксплойта, контроллеры и список запатченных пакетов идентичны — отличается только TargetFramework.
Он существует потому, что большинство корпоративных заказчиков не могут перейти на новейший .NET SDK по требованию. .NET 7 достиг конца поддержки 14 мая 2024 года, но реальные производственные среды всё ещё работают на нём по причинам совместимости, сертификации или эксплуатации. Именно для этого и создан Seal Security: когда заказчик не может (или не хочет) делать мажорное обновление версии, Seal патчит уязвимую зависимость на месте в той же версии, без изменения публичного API и без правок кода приложения заказчика. Эта демонстрация позволяет провести такой разговор на реальном стеке заказчика, а не просить его сначала установить net8/net9.
Форк фиксирует SDK на 7.0.x через global.json, чтобы случайные обновления не проскочили во время демонстрации.
Это демонстрационное приложение — простая стартовая страница ASP.NET Core, которая использует Newtonsoft.Json 12.0.2 для разбора пользовательского ввода как объекта конфигурации. У приложения есть поле имени — введите своё имя, нажмите Go, и оно отобразит «Welcome, alice!». Под капотом ввод передаётся через JsonConvert.DeserializeObject<NestedConfig>() библиотеки Newtonsoft.Json. Вот и всё — совершенно стандартное использование популярной JSON-библиотеки.
Проблема в том, что Newtonsoft.Json 12.0.2 (и версии до 13.0.1) содержит CVE-2024-21907 — уязвимость типа «Отказ в обслуживании» высокой степени серьёзности с оценкой CVSS 7.5 (HIGH). Эта демонстрация показывает, как Seal Security патчит уязвимость на месте без необходимости мажорного обновления версии.
Метод JsonConvert.DeserializeObject<T>() библиотеки Newtonsoft.Json может быть использован путём создания глубоко вложенных JSON-нагрузок. При десериализации в типизированный объект (POCO) JsonSerializerInternalReader библиотеки выполняет по-настоящему рекурсивные вызовы (CreateValueInternal → CreateObject → PopulateObject → SetPropertyValue → CreateValueInternal), которые вызывают переполнение стека, что приводит к падению приложения (отказ в обслуживании).
Приложение принимает пользовательский ввод и разбирает его через Newtonsoft.Json. Если ввод является URL-адресом, приложение сначала загружает содержимое — реалистичный шаблон, используемый загрузчиками конфигураций, тестерами API и приёмниками вебхуков:
public class NestedConfig
{
[JsonProperty("n")]
public NestedConfig? N { get; set; }
}
var config = JsonConvert.DeserializeObject<NestedConfig>(name);
Обычный ввод: Введите alice → отобразится «Welcome, alice!»
Эксплойт: Вставьте этот URL в поле имени и нажмите Go:
https://raw.githubusercontent.com/seal-sec-demo-2/json-payload/main/payload.json
Приложение определяет, что это URL, загружает json-payload (глубоко вложенный JSON {"n":{"n":{...}}}) и десериализует его через Newtonsoft.Json в рекурсивный класс NestedConfig — вызывая переполнение стека.
JsonSerializerInternalReader рекурсивно проходит через CreateValueInternal → CreateObject → PopulateObject → SetPropertyValue для каждого уровня вложенности. На глубине ~5000 уровней это исчерпывает стек потока, и приложение падает с StackOverflowException — процесс умирает мгновенно (обработка ошибок невозможна).
С помощью этой уязвимости атакующие могут:
Общедоступное исправление требует обновления до версии 13.0.1. Однако обновление мажорных версий часто вносит:
Это превращает «простое обновление» в проект, который легко может занять недели времени разработчиков — оставляя уязвимость открытой в это время.
Запатченная версия Seal (12.0.2-sp1) добавляет защиту от глубины рекурсии без изменения какого-либо публичного API. Патч:
MaxDepth по умолчанию для предотвращения неограниченной рекурсииЭто та же стратегия смягчения, что применяется в Newtonsoft.Json 13.0.1, перенесённая на 12.0.2 как замена без изменений.
Эта демонстрация также включает другие уязвимые NuGet-пакеты, которые Seal Security может патчить:
Уязвимость «Внешняя сущность XML» (XXE) в разборе XML-конфигурации log4net. Атакующий, контролирующий файл конфигурации log4net, может:
Примечание о
System.Net.Http: Каноническая демонстрация net9 также поставляет уязвимую ссылкуSystem.Net.Http 4.3.0для CVE-2017-0249. Мы исключили её из этого форка net7, потому что в .NET 7System.Net.Httpявляется частью BCL, а отдельная ссылка на пакет — это рудиментарный мета-пакет; у него есть известные крайние случаи сdotnet add package --source <local-nupkg>, а именно так CLI Seal применяет запатченные версии. Её исключение делает шагseal fixнадёжным без изменения истории демонстрации (HttpClientпо-прежнему работает отлично; его предоставляет рантайм).
Двоичные файлы CLI для Windows были прекращены после v0.3.238. v0.3.238 полностью функционален для устранения проблем NuGet в Windows.
Подробное руководство по установке и запуску на Windows Server находится в README-WINDOWS-SERVER.md. Краткое руководство ниже охватывает те же шаги в сжатой форме.
PowerShell:
$env:SEAL_TOKEN = "your-seal-token-here"
$env:SEAL_PROJECT = "nuget-demo-net7"
cd seal-security-nuget-demo-net7
# Восстановление (тянет с nuget.org и канала Seal — см. nuget.config)
dotnet restore
# Сборка и запуск
dotnet build
dotnet run
Откройте http://localhost:5000 — приложение работает с уязвимыми зависимостями.
Введите alice в поле имени, нажмите Go. Вы должны увидеть: «Welcome, alice!»
Вставьте следующий URL в поле имени и нажмите Go:
https://raw.githubusercontent.com/seal-sec-demo-2/json-payload/main/payload.json