
Форк .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: когда заказчик не может (или не хочет) делать major version bump, 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 исправляет уязвимость на месте, не требуя обновления major версии.
Метод 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. Однако обновление major версий часто влечёт:
Это делает исправление «просто обновитесь» проектом, который может легко занять недели времени разработчика — оставляя уязвимость открытой тем временем.
Запатченная версия от 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 = "ваш-токен-seal-здесь"
$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
Результат без патча: Браузер показывает ошибку / сброс соединения — приложение упало с StackOverflowException в JsonSerializerInternalReader.CreateValueInternal. Процесс мёртв.
# (Необязательно — уже сделано выше) Сначала восстановите зависимости
dotnet restore
# Запустите CLI Seal для исправления уязвимостей
seal fix . --mode remote -v
# Восстановите снова, чтобы получить запатченные версии
dotnet restore
# Соберите и запустите запатченное приложение
dotnet build
dotnet run
Теперь приложение использует запатченные версии (Newtonsoft.Json 12.0.2-sp1, log4net 2.0.5-sp1).
Результат с патчем: Вставьте тот же URL эксплойта → страница показывает «Blocked by Seal patch: MaxDepth of 64 has been exceeded.» — запатченный лимит рекурсии Newtonsoft.Json отклонил глубокую полезную нагрузку. Сервер продолжает нормальную работу.
dotnet list package
Вы должны увидеть пакеты с суффиксом -sp1, указывающим на патчи Seal Security.
Шаг CLI должен быть добавлен сразу после установки зависимостей, но до финальной сборки.
# 1. Восстановление зависимостей
dotnet restore
# 2. <--- Запустите Seal CLI здесь
$env:SEAL_TOKEN = "ваш-токен-seal-здесь"
$env:SEAL_PROJECT = "nuget-demo-net7"
seal fix . --mode remote -v
# 3. Восстановите снова (чтобы получить запатченные версии)
dotnet restore
# 4. Сборка
dotnet build
| Режим | Описание |
|---|---|
all | Автоматически применить все доступные исправления |
remote | Применять только исправления, одобренные в интерфейсе Seal |
local | Применять только исправления, определённые в .seal-actions.yml |
.seal-actions.yml в этом репозитории уже перечисляет три запатченных переопределения для режима local, поэтому seal fix . --mode local -v работает офлайн (всё ещё требуется токен для сервера артефактов).
nuget.config предварительно настроен на использование Seal Security с переменными окружения:
<configuration>
<packageSources>
<add key="Seal" value="https://nuget.sealsecurity.io/v3/index.json" />
<add key="nuget.org" value="https://api.nuget.org/v3/index.json" />
</packageSources>
<packageSourceCredentials>
<Seal>
<add key="Username" value="%SEAL_PROJECT%" />
<add key="ClearTextPassword" value="%SEAL_TOKEN%" />
</Seal>
</packageSourceCredentials>
</configuration>
| Переменная | Описание |
|---|---|
SEAL_TOKEN | Ваш токен доступа Seal Security |
SEAL_PROJECT | ID проекта (например, nuget-demo-net7) |
CLI Seal нуждается в исходящем HTTPS (TCP 443) к:
cli.sealsecurity.io — сканирование / конфигурация исправленияauthorization.sealsecurity.io — проверка токенаnuget.sealsecurity.io — загрузка запатченных .nupkgd2zko6i8myndc4.cloudfront.net — CDN, обслуживающая фактические запатченные артефакты (имена хостов .sealsecurity.io перенаправляют сюда)api.nuget.org / стандартные конечные точки nuget.org — для незапатченных зависимостейПроверьте из PowerShell после открытия брандмауэра:
Test-NetConnection cli.sealsecurity.io -Port 443
Test-NetConnection authorization.sealsecurity.io -Port 443
Test-NetConnection nuget.sealsecurity.io -Port 443
Test-NetConnection d2zko6i8myndc4.cloudfront.net -Port 443
Все должны сообщать TcpTestSucceeded: True.
12.0.2-sp1 является двоично-совместимой заменой 12.0.2.Пакеты, используемые в этой демонстрации:
| Пакет | Уязвимая версия | Запатченная версия | CVE | CVSS |
|---|
Другие запатченные пакеты NuGet, доступные из фида Seal (не в этой демонстрации, перечислены для справки):
Лицензия MIT — см. файл LICENSE для подробностей.
| Элемент | Почему это важно |
|---|
global.json фиксирует SDK на 7.0.x с rollForward: latestFeature | Предотвращает автоматическое переключение SDK на net8/net9 на машинах с несколькими установленными SDK во время демонстрации. |
System.Configuration.ConfigurationManager зафиксирован на 7.0.0 | Каноническое демо для net9 использует 8.0.0, который предназначен только для net8 и не восстанавливается на net7. 7.0.0 имеет ту же поверхность API, которая нужна log4net. |
NU1701 подавлено в csproj | log4net 2.0.5 рекламирует устаревший TFM net4x, который .NET 7 принимает во время выполнения, но предупреждает во время восстановления. Предупреждение косметическое; подавление сохраняет чистый вывод сборки во время демонстрации. |
| Seal CLI v0.3.238 для Windows x64 | Последний выпуск с двоичным файлом для Windows; полностью функционален для исправления NuGet. Двоичные файлы для Windows были прекращены после этой версии, поэтому не предлагайте более новую версию. |
| Newtonsoft.Json | 12.0.2 | 12.0.2-sp1 | CVE-2024-21907 | 7.5 HIGH |
| log4net | 2.0.5 | 2.0.5-sp1 | CVE-2018-1285 | 9.8 CRITICAL |
| Пакет | Уязвимая версия | Запатченная версия | CVE | CVSS |
|---|
| log4net | 2.0.0 | 2.0.0-sp1 | CVE-2018-1285 | 9.8 CRITICAL |
| System.Net.Http | 4.3.0 | 4.3.0-sp1 | CVE-2017-0249 | 7.3 HIGH |
| Snappier | 1.1.0 | 1.1.0-sp1 | CVE-2023-28638 | 7.0 HIGH |
| jQuery.Validation | 1.17.0 | 1.17.0-sp1 | CVE-2021-21252 | 7.5 HIGH |