
.NET 7 fork de seal-security-nuget-demo: la misma historia de explotación de CVE-2024-21907, redirigida para clientes bloqueados en .NET SDK 7.
Este es un fork redirigido del demo canónico seal-security-nuget-demo (que apunta a net9.0). La historia del exploit, los controladores y la lista de paquetes sellados son idénticos — solo difiere el TargetFramework.
Existe porque la mayoría de los clientes empresariales no pueden migrar al SDK de .NET más reciente bajo demanda. .NET 7 alcanzó el fin de soporte el 14 de mayo de 2024, pero los entornos de producción reales aún lo utilizan por razones de compatibilidad, certificación u operativas. Ese es precisamente el caso para el que está diseñado Seal Security: cuando un cliente no puede (o no quiere) dar un salto de versión mayor, Seal parchea la dependencia vulnerable en su lugar bajo la misma versión, sin cambios en la API pública ni ediciones de código en la aplicación del cliente. Este demo permite que esa conversación ocurra en la pila real del cliente en lugar de pedirle que instale primero net8/net9.
El fork fija el SDK a 7.0.x mediante global.json para que las actualizaciones accidentales no se cuelen durante la demostración.
Esta aplicación de demostración es una página de bienvenida simple de ASP.NET Core que utiliza Newtonsoft.Json 12.0.2 para analizar la entrada del usuario como un objeto de configuración. La aplicación tiene un campo de nombre: escribe tu nombre, haz clic en Ir, y muestra "¡Bienvenido, alice!". Internamente pasa la entrada a través de JsonConvert.DeserializeObject<NestedConfig>() de Newtonsoft.Json. Eso es todo — uso completamente estándar de una biblioteca JSON popular.
El problema es que Newtonsoft.Json 12.0.2 (y versiones anteriores a 13.0.1) tiene CVE-2024-21907 — una vulnerabilidad de Denegación de Servicio de alta severidad con una puntuación CVSS de 7.5 (ALTA). Este demo muestra cómo Seal Security parchea la vulnerabilidad en su lugar sin requerir una actualización de versión mayor.
El método JsonConvert.DeserializeObject<T>() de Newtonsoft.Json puede ser explotado creando payloads JSON profundamente anidados. Al deserializar en un objeto tipado (POCO), el JsonSerializerInternalReader de la biblioteca realiza llamadas verdaderamente recursivas (CreateValueInternal → CreateObject → PopulateObject → SetPropertyValue → CreateValueInternal) que causan desbordamiento de pila, lo que provoca el bloqueo de la aplicación (Denegación de Servicio).
La aplicación toma la entrada del usuario y la analiza a través de Newtonsoft.Json. Si la entrada es una URL, la aplicación primero obtiene el contenido — un patrón realista utilizado por cargadores de configuración, probadores de API y receptores de webhooks:
public class NestedConfig
{
[JsonProperty("n")]
public NestedConfig? N { get; set; }
}
var config = JsonConvert.DeserializeObject<NestedConfig>(name);
Entrada normal: Escribe alice → muestra "¡Bienvenido, alice!"
Exploit: Pega esta URL en el campo de nombre y haz clic en Ir:
https://raw.githubusercontent.com/seal-sec-demo-2/json-payload/main/payload.json
La aplicación detecta que es una URL, obtiene el json-payload (JSON profundamente anidado {"n":{"n":{...}}}), y lo deserializa a través de Newtonsoft.Json en la clase recursiva NestedConfig — desencadenando el desbordamiento de pila.
El JsonSerializerInternalReader recurre a través de CreateValueInternal → CreateObject → PopulateObject → SetPropertyValue por cada nivel de anidamiento. A ~5,000 niveles de profundidad, esto agota la pila del hilo y la aplicación se bloquea con una StackOverflowException — el proceso muere instantáneamente (sin manejo de errores elegante posible).
Con esta vulnerabilidad, los atacantes pueden:
La corrección disponible públicamente requiere actualizar a la versión 13.0.1. Sin embargo, actualizar versiones mayores a menudo introduce:
Esto hace que la corrección de "simplemente actualizar" sea un proyecto que puede fácilmente tomar semanas de tiempo de desarrollo — dejando la vulnerabilidad abierta mientras tanto.
La versión parcheada de Seal (12.0.2-sp1) añade protección de profundidad de recursión sin cambiar ninguna API pública. El parche:
MaxDepth predeterminados para prevenir recursión ilimitadaEsta es la misma estrategia de mitigación aplicada en Newtonsoft.Json 13.0.1, adaptada a 12.0.2 como reemplazo directo.
Este demo también incluye otros paquetes NuGet vulnerables que Seal Security puede parchear:
Vulnerabilidad de Entidad Externa XML (XXE) en el análisis de configuración XML de log4net. Un atacante que pueda controlar el archivo de configuración de log4net puede:
Nota sobre
System.Net.Http: El demo canónico de net9 también incluye una referencia vulnerable aSystem.Net.Http 4.3.0para CVE-2017-0249. Lo hemos omitido de este fork de net7 porque en .NET 7System.Net.Httpes parte de la BCL y la referencia al paquete independiente es un meta-paquete vestigial — tiene casos límite conocidos condotnet add package --source <local-nupkg>, que es exactamente cómo el CLI de Seal aplica versiones selladas. Eliminarlo hace que el paso deseal fixsea confiable sin cambiar la historia del demo (HttpClientsigue funcionando bien; el runtime lo proporciona).
Los binarios del CLI de Windows se descontinuaron después de v0.3.238. v0.3.238 es completamente funcional para la remediación de NuGet en Windows.
Una guía detallada de instalación y ejecución en Windows Server está en README-WINDOWS-SERVER.md. El Inicio Rápido a continuación cubre los mismos pasos en forma condensada.
PowerShell:
$env:SEAL_TOKEN = "tu-token-de-seal-aqui"
$env:SEAL_PROJECT = "nuget-demo-net7"
cd seal-security-nuget-demo-net7
# Restaurar (obtiene de nuget.org y del feed de Seal — ver nuget.config)
dotnet restore
# Compilar y ejecutar
dotnet build
dotnet run
Abre http://localhost:5000 — la aplicación se está ejecutando con dependencias vulnerables.
Escribe alice en el campo de nombre, haz clic en Ir. Deberías ver: "¡Bienvenido, alice!"
Pega la siguiente URL en el campo de nombre y haz clic en Ir:
https://raw.githubusercontent.com/seal-sec-demo-2/json-payload/main/payload.json
Resultado sin parche: El navegador muestra un error / restablecimiento de conexión — la aplicación se bloqueó con una StackOverflowException en JsonSerializerInternalReader.CreateValueInternal. El proceso está muerto.
# (Opcional — ya hecho arriba) Restaurar dependencias primero
dotnet restore
# Ejecutar el CLI de Seal para corregir vulnerabilidades
seal fix . --mode remote -v
# Restaurar nuevamente para obtener versiones selladas
dotnet restore
# Compilar y ejecutar la aplicación parcheada
dotnet build
dotnet run
La aplicación ahora usa versiones parcheadas (Newtonsoft.Json 12.0.2-sp1, log4net 2.0.5-sp1).
Resultado parcheado: Pega la misma URL de exploit → la página muestra "Bloqueado por el parche de Seal: Se ha excedido MaxDepth de 64." — el límite de recursión parcheado de Newtonsoft.Json rechazó el payload profundo. El servidor continúa ejecutándose normalmente.
dotnet list package
Deberías ver paquetes con el sufijo -sp1 que indican los parches de Seal Security.
El paso del CLI debe añadirse inmediatamente después de que se instalen las dependencias pero antes de la compilación final.
# 1. Restaurar dependencias
dotnet restore
# 2. <--- Ejecutar el CLI de Seal Aquí
$env:SEAL_TOKEN = "tu-token-de-seal-aqui"
$env:SEAL_PROJECT = "nuget-demo-net7"
seal fix . --mode remote -v
# 3. Restaurar nuevamente (para obtener versiones selladas)
dotnet restore
# 4. Compilar
dotnet build
| Modo | Descripción |
|---|---|
all | Aplicar todas las correcciones disponibles automáticamente |
remote | Aplicar solo las correcciones aprobadas en la interfaz de Seal |
local | Aplicar solo las correcciones definidas en .seal-actions.yml |
.seal-actions.yml en este repositorio ya lista las tres anulaciones selladas para el modo local, por lo que seal fix . --mode local -v funciona sin conexión (aún necesita token para el servidor de artefactos).
nuget.config está preconfigurado para usar Seal Security con variables de entorno:
<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>
| Variable | Descripción |
|---|---|
SEAL_TOKEN | Tu token de acceso de Seal Security |
SEAL_PROJECT | ID del proyecto (ej., nuget-demo-net7) |
El CLI de Seal necesita HTTPS saliente (TCP 443) hacia:
cli.sealsecurity.io — configuración de escaneo / correcciónauthorization.sealsecurity.io — validación de tokennuget.sealsecurity.io — descargas de .nupkg selladosd2zko6i8myndc4.cloudfront.net — CDN que sirve los artefactos sellados reales (los nombres de host .sealsecurity.io redirigen aquí)api.nuget.org / endpoints estándar de nuget.org — para dependencias no selladasVerifica desde PowerShell después de abrir el firewall:
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
Todos deberían informar TcpTestSucceeded: True.
| Elemento | Por qué importa |
|---|---|
global.json fija el SDK a 7.0.x con rollForward: latestFeature | Evita que máquinas con net8/net9 en paralelo cambien silenciosamente de SDK a mitad de la demostración. |
System.Configuration.ConfigurationManager fijado a 7.0.0 | El demo canónico de net9 usa 8.0.0, que apunta solo a net8 y falla al restaurar en net7. 7.0.0 tiene la misma superficie de API que log4net necesita. |
NU1701 suprimido en el csproj | log4net 2.0.5 anuncia un TFM heredado net4x que .NET 7 acepta en tiempo de ejecución pero advierte al restaurar. La advertencia es cosmética; la supresión mantiene limpia la salida de compilación durante la demostración. |
| CLI de Seal v0.3.238 para Windows x64 | Última versión con binario de Windows; completamente funcional para la remediación de NuGet. Los binarios de Windows se descontinuaron después de esta versión, por lo que no se debe sugerir una versión más reciente. |
12.0.2-sp1 es un reemplazo directo compatible a nivel binario para 12.0.2.Paquetes utilizados por este demo:
| Paquete | Versión Vulnerable | Versión Sellada | CVE | CVSS |
|---|---|---|---|---|
| Newtonsoft.Json | 12.0.2 | 12.0.2-sp1 | CVE-2024-21907 | 7.5 ALTA |
| log4net | 2.0.5 | 2.0.5-sp1 | CVE-2018-1285 | 9.8 CRÍTICA |
Otros paquetes NuGet sellados disponibles desde el feed de Seal (no en este demo, listados como referencia):
| Paquete | Versión Vulnerable | Versión Sellada | CVE | CVSS |
|---|---|---|---|---|
| log4net | 2.0.0 | 2.0.0-sp1 | CVE-2018-1285 | 9.8 CRÍTICA |
| System.Net.Http | 4.3.0 | 4.3.0-sp1 | CVE-2017-0249 | 7.3 ALTA |
| Snappier | 1.1.0 | 1.1.0-sp1 | CVE-2023-28638 | 7.0 ALTA |
| jQuery.Validation | 1.17.0 | 1.17.0-sp1 | CVE-2021-21252 | 7.5 ALTA |
Licencia MIT - Ver el archivo LICENSE para más detalles.