
.NET 7 fork di seal-security-nuget-demo: stessa storia di exploit CVE-2024-21907, reindirizzato per i clienti vincolati a .NET SDK 7.
Questo è un fork riadattato del demo canonico seal-security-nuget-demo (che punta a net9.0). La storia dell'exploit, i controller e l'elenco dei pacchetti sigillati sono identici — cambia solo la TargetFramework.
Esiste perché la maggior parte dei clienti enterprise non può passare al più recente .NET SDK su richiesta. .NET 7 ha raggiunto la fine del supporto il 14 maggio 2024, ma molti ambienti di produzione reali continuano a usarlo per motivi di compatibilità, certificazione o operatività. Questo è esattamente il caso per cui Seal Security è progettata: quando un cliente non può (o non vuole) fare un salto di versione maggiore, Seal corregge la dipendenza vulnerabile sul posto mantenendo la stessa versione, senza modifiche all'API pubblica e senza modifiche al codice dell'applicazione del cliente. Questo demo consente di avere questa conversazione sullo stack reale del cliente invece di chiedergli di installare prima net8/net9.
Il fork fissa l'SDK alla versione 7.0.x tramite global.json così da evitare che aggiornamenti accidentali si insinuino durante il demo.
Questa applicazione demo è una semplice pagina di benvenuto ASP.NET Core che usa Newtonsoft.Json 12.0.2 per analizzare l'input dell'utente come oggetto di configurazione. L'app ha un campo nome — digita il tuo nome, clicca su Go, e mostra "Welcome, alice!". Sotto il cofano passa l'input attraverso JsonConvert.DeserializeObject<NestedConfig>() di Newtonsoft.Json. Tutto qui — un utilizzo completamente standard di una popolare libreria JSON.
Il problema è che Newtonsoft.Json 12.0.2 (e le versioni precedenti alla 13.0.1) presenta CVE-2024-21907 — una vulnerabilità Denial of Service ad alta gravità con punteggio CVSS di 7.5 (ALTO). Questo demo mostra come Seal Security corregge la vulnerabilità sul posto senza richiedere un aggiornamento di versione maggiore.
Il metodo JsonConvert.DeserializeObject<T>() di Newtonsoft.Json può essere sfruttato creando payload JSON annidati in profondità. Quando si deserializza in un oggetto tipizzato (POCO), il JsonSerializerInternalReader della libreria esegue chiamate realmente ricorsive (CreateValueInternal → CreateObject → PopulateObject → SetPropertyValue → CreateValueInternal) che causano stack overflow, portando al crash dell'applicazione (Denial of Service).
L'app prende l'input dell'utente e lo analizza tramite Newtonsoft.Json. Se l'input è un URL, l'app recupera prima il contenuto — un pattern realistico usato da config loader, API tester e webhook receiver:
public class NestedConfig
{
[JsonProperty("n")]
public NestedConfig? N { get; set; }
}
var config = JsonConvert.DeserializeObject<NestedConfig>(name);
Input normale: Digita alice → mostra "Welcome, alice!"
Exploit: Incolla questo URL nel campo nome e clicca su Go:
https://raw.githubusercontent.com/seal-sec-demo-2/json-payload/main/payload.json
L'app rileva che è un URL, recupera il json-payload (JSON annidato in profondità {"n":{"n":{...}}}) e lo deserializza tramite Newtonsoft.Json nella classe ricorsiva NestedConfig — innescando lo stack overflow.
Il JsonSerializerInternalReader ricorre attraverso CreateValueInternal → CreateObject → PopulateObject → SetPropertyValue per ogni livello di annidamento. A circa ~5.000 livelli di profondità, questo esaurisce lo stack del thread e l'applicazione va in crash con una StackOverflowException — il processo muore all'istante (nessuna gestione degli errori elegante possibile).
Con questa vulnerabilità, gli attaccanti possono:
La correzione pubblicamente disponibile richiede l'aggiornamento alla versione 13.0.1. Tuttavia, aggiornare le versioni maggiori spesso introduce:
Questo rende la correzione "basta aggiornare" un progetto che può facilmente richiedere settimane di tempo agli sviluppatori — lasciando la vulnerabilità aperta nel frattempo.
La versione corretta di Seal (12.0.2-sp1) aggiunge protezione sulla profondità di ricorsione senza cambiare alcuna API pubblica. La correzione:
MaxDepth predefiniti per prevenire ricorsioni illimitateQuesta è la stessa strategia di mitigazione applicata in Newtonsoft.Json 13.0.1, riportata alla 12.0.2 come sostituto drop-in.
Questo demo include anche altri pacchetti NuGet vulnerabili che Seal Security può correggere:
Vulnerabilità XML External Entity (XXE) nell'analisi della configurazione XML di log4net. Un attaccante che può controllare il file di configurazione di log4net può:
Nota su
System.Net.Http: Il demo canonico net9 include anche un riferimento vulnerabile aSystem.Net.Http 4.3.0per CVE-2017-0249. L'abbiamo omesso da questo fork net7 perché su .NET 7System.Net.Httpfa parte della BCL e il riferimento al pacchetto standalone è un meta-pacchetto vestigiale — ha casi limite noti condotnet add package --source <local-nupkg>, che è esattamente il modo in cui la CLI Seal applica le versioni sigillate. Rimuoverlo rende il passaggioseal fixaffidabile senza cambiare la storia del demo (HttpClientfunziona comunque perfettamente; lo fornisce il runtime).
I binari CLI per Windows sono stati interrotti dopo la v0.3.238. La v0.3.238 è completamente funzionale per la correzione NuGet su Windows.
Una guida dettagliata per installazione ed esecuzione su Windows Server è in README-WINDOWS-SERVER.md. La Guida Rapida qui sotto copre gli stessi passaggi in forma condensata.
PowerShell:
$env:SEAL_TOKEN = "your-seal-token-here"
$env:SEAL_PROJECT = "nuget-demo-net7"
cd seal-security-nuget-demo-net7
# Ripristina (scarica da nuget.org e dal feed Seal — vedi nuget.config)
dotnet restore
# Compila ed esegui
dotnet build
dotnet run
Apri http://localhost:5000 — l'app è in esecuzione con dipendenze vulnerabili.
Digita alice nel campo nome, clicca su Go. Dovresti vedere: "Welcome, alice!"
Incolla il seguente URL nel campo nome e clicca su Go:
https://raw.githubusercontent.com/seal-sec-demo-2/json-payload/main/payload.json
Risultato senza correzione: Il browser mostra un errore / connessione reimpostata — l'app è andata in crash con una StackOverflowException in JsonSerializerInternalReader.CreateValueInternal. Il processo è morto.
# (Opzionale — già fatto sopra) Ripristina prima le dipendenze
dotnet restore
# Esegui la CLI Seal per correggere le vulnerabilità
seal fix . --mode remote -v
# Ripristina di nuovo per scaricare le versioni sigillate
dotnet restore
# Compila ed esegui l'app corretta
dotnet build
dotnet run
L'app ora usa versioni corrette (Newtonsoft.Json 12.0.2-sp1, log4net 2.0.5-sp1).
Risultato con correzione: Incolla lo stesso URL exploit → la pagina mostra "Blocked by Seal patch: MaxDepth of 64 has been exceeded." — il limite di ricorsione corretto di Newtonsoft.Json ha rifiutato il payload profondo. Il server continua a funzionare normalmente.
dotnet list package
Dovresti vedere pacchetti con suffisso -sp1 che indicano le correzioni Seal Security.
Il passaggio della CLI deve essere aggiunto immediatamente dopo l'installazione delle dipendenze ma prima della compilazione finale.
# 1. Ripristina le dipendenze
dotnet restore
# 2. <--- Esegui la CLI Seal Qui
$env:SEAL_TOKEN = "your-seal-token-here"
$env:SEAL_PROJECT = "nuget-demo-net7"
seal fix . --mode remote -v
# 3. Ripristina di nuovo (per ottenere le versioni sigillate)
dotnet restore
# 4. Compila
dotnet build
| Modalità | Descrizione |
|---|---|
all | Applica automaticamente tutte le correzioni disponibili |
remote | Applica solo le correzioni approvate nella UI Seal |
local | Applica solo le correzioni definite in .seal-actions.yml |
.seal-actions.yml in questo repository elenca già le tre override sigillate per la modalità local, quindi seal fix . --mode local -v funziona offline (serve comunque il token per il server degli artefatti).
nuget.config è pre-configurato per usare Seal Security con variabili d'ambiente:
<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>
| Variabile | Descrizione |
|---|---|
SEAL_TOKEN | Il tuo token di accesso Seal Security |
SEAL_PROJECT | ID del progetto (es., nuget-demo-net7) |
La CLI Seal necessita di HTTPS in uscita (TCP 443) verso:
cli.sealsecurity.io — configurazione scan / fixauthorization.sealsecurity.io — validazione tokennuget.sealsecurity.io — download dei .nupkg sigillatid2zko6i8myndc4.cloudfront.net — CDN che serve gli artefatti sigillati effettivi (gli hostname .sealsecurity.io reindirizzano qui)api.nuget.org / endpoint standard nuget.org — per le dipendenze non sigillateVerifica da PowerShell dopo aver aperto il 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
Tutti dovrebbero riportare TcpTestSucceeded: True.
| Elemento | Perché è importante |
|---|---|
global.json fissa l'SDK a 7.0.x con rollForward: latestFeature | Impedisce alle macchine con net8/net9 affiancati di cambiare silenziosamente SDK a metà demo. |
System.Configuration.ConfigurationManager fissato a 7.0.0 | Il demo canonico net9 usa la 8.0.0, che punta solo a net8 e non riesce a ripristinare su net7. La 7.0.0 ha la stessa superficie API di cui log4net ha bisogno. |
NU1701 soppresso nel csproj | log4net 2.0.5 pubblicizza un TFM legacy net4x che .NET 7 accetta a runtime ma avvisa al ripristino. L'avviso è puramente estetico; la soppressione mantiene pulito l'output di compilazione durante il demo. |
| Seal CLI v0.3.238 per Windows x64 | Ultima release con binario Windows; completamente funzionale per la correzione NuGet. I binari Windows sono stati interrotti dopo questa versione, quindi non suggerire release più recenti. |
12.0.2-sp1 è un sostituto drop-in binario-compatibile per 12.0.2.Pacchetti usati da questo demo:
| Pacchetto | Versione Vulnerabile | Versione Sigillata | CVE | CVSS |
|---|---|---|---|---|
| Newtonsoft.Json | 12.0.2 | 12.0.2-sp1 | CVE-2024-21907 | 7.5 ALTO |
| log4net | 2.0.5 | 2.0.5-sp1 | CVE-2018-1285 | 9.8 CRITICO |
Altri pacchetti NuGet sigillati disponibili dal feed Seal (non in questo demo, elencati per riferimento):
| Pacchetto | Versione Vulnerabile | Versione Sigillata | CVE | CVSS |
|---|---|---|---|---|
| log4net | 2.0.0 | 2.0.0-sp1 | CVE-2018-1285 | 9.8 CRITICO |
| System.Net.Http | 4.3.0 | 4.3.0-sp1 | CVE-2017-0249 | 7.3 ALTO |
| Snappier | 1.1.0 | 1.1.0-sp1 | CVE-2023-28638 | 7.0 ALTO |
| jQuery.Validation | 1.17.0 | 1.17.0-sp1 | CVE-2021-21252 | 7.5 ALTO |
Licenza MIT - Vedi il file LICENSE per i dettagli.