Nota: Modificato il 22 giugno 2023 per aggiornare la risoluzione e le soluzioni alternative
Nota: Modificato il 15 giugno 2023 per aggiornare le opzioni 4 e 5
Priorità bassa
Il 13 giugno 2023 Microsoft ha rilasciato un aggiornamento della sicurezza per .NET Framework e .NET che influisce sul modo in cui il runtime importa i certificati X.509. Queste modifiche potrebbero causare l'importazione del certificato X.509 a generare CryptographicException negli scenari in cui l'importazione sarebbe riuscita prima dell'aggiornamento.
Questo documento descrive le modifiche e le soluzioni alternative disponibili per le applicazioni interessate.
Software interessato
-
.NET Framework 2.0
-
.NET Framework 4.6.2, 4.7, 4.7.1, 4.7.2
-
.NET Framework 4.8
-
.NET Framework 4.8.1
-
.NET 6.0
-
.NET 7.0
API interessate
Descrizione della modifica
Prima della modifica del 13 giugno 2023, quando .NET Framework e .NET vengono presentati con un BLOB di certificato binario per l'importazione, .NET Framework e .NET delegano in genere la convalida e l'importazione del BLOB nel sistema operativo sottostante. Ad esempio, in Windows, .NET Framework e .NET in genere si basano sull'API PFXImportCertStore per la convalida e l'importazione.
A partire dal 13 giugno 2023, la modifica, quando .NET Framework e .NET viene presentato con un BLOB di certificato binario per l'importazione, .NET Framework e .NET eseguiranno in alcuni casi una convalida aggiuntiva prima di consegnare il BLOB al sistema operativo sottostante. Questa convalida aggiuntiva esegue una serie di controlli euristici per determinare se il certificato in arrivo esaurisce le risorse in seguito all'importazione. Poiché si tratta di una convalida aggiuntiva oltre a quella normalmente eseguita dal sistema operativo sottostante, è possibile bloccare i BLOB dei certificati che sarebbero stati importati correttamente prima della modifica del 13 giugno 2023.
Regressioni note
-
Se un certificato X.509 è stato esportato come BLOB PFX usando un numero insolitamente elevato di iterazioni delle password, l'importazione del certificato potrebbe non riuscire. La maggior parte delle strutture di esportazione dei certificati usa un numero di iterazioni compreso tra 2.000 e 10.000. Dopo l'applicazione dell'aggiornamento della sicurezza, l'importazione non riuscirà per i certificati contenenti un numero di iterazione maggiore di 600.000.
-
Se un certificato X.509 è stato esportato con una password Null (ad esempio, tramiteX509Certificate.Export(X509ContentType.Pfx, (string)null)o ilX509Certificate.Export(X509ContentType.Pfx)]senza password), l'importazione del certificato potrebbe non riuscire.
Nota: La regressione precedente è stata risolta nell'aggiornamento del 22 giugno 2023 discusso in KB5028608.
-
Se un certificato X.509 è stato esportato come BLOB PFX usando la funzionalità di Windows per proteggere la chiave privata in un SID, l'importazione del certificato potrebbe ora non riuscire. Questo influirà sui BLOB PFX creati nei modi seguenti:
-
Tramite l'Esportazione guidata certificati di Windows e specificando nella procedura guidata che la chiave privata deve essere protetta per un utente di dominio; O
-
Tramite il cmdlet Export-PfxCertificate di PowerShell in cui viene fornito un argomento -ProtectTo esplicito; O
-
Tramite l'utilità certutil in cui viene fornito un argomento -protectto esplicito; O
-
Tramite l'API PFXExportCertStoreEx in cui viene fornito il flag di PKCS12_PROTECT_TO_DOMAIN_SIDS.
-
Soluzioni & soluzioni alternative
Esistono varie soluzioni alternative, a seconda che si vogliano apportare modifiche mirate a singoli siti di chiamata all'interno del codice, se si vuole modificare il comportamento di una singola applicazione o se si vogliono apportare modifiche a livello di computer.
Opzione 1 (preferita) - Installare una patch aggiornata
Nota: Questa è l'opzione preferita perché risolve le regressioni dei clienti comunemente segnalate e non richiede modifiche di codice all'applicazione.
Applicabilità: questa opzione si applica a tutte le versioni di .NET Framework e .NET.
Questo problema è stato risolto nell'aggiornamento del 22 giugno 2023 discusso in KB5028608.
Microsoft consiglia ai clienti che stanno riscontrando regressioni introdotte entro il 13 giugno 2023 di provare a installare questa patch aggiornata prima di provare le soluzioni alternative elencate più avanti in questo documento.
Opzione 2 - Modifica del sito di chiamata
Applicabilità: questa opzione si applica a tutte le versioni di .NET Framework e .NET.
Valutare se il BLOB da importare è attendibile. Ad esempio, il BLOB è stato recuperato da un percorso attendibile, ad esempio un database o un file di configurazione sotto il controllo dell'utente, oppure è stato fornito tramite una richiesta di rete effettuata da un client non autenticato o non privato?
Microsoft consiglia vivamente di non importare blob PFX forniti da client non autenticati o non privati, in quanto questi BLOB potrebbero contenere comportamenti dannosi di esaurimento delle risorse.
Se è necessario importare un BLOB di certificato di chiave pubblica fornito da un utente non attendibile, è possibile usare il codice seguente per importare in modo sicuro un BLOB di questo tipo. Questo codice di esempio usa il metodo GetCertContentType per determinare qual è il tipo sottostante del BLOB del certificato e rifiuta i BLOB PFX nei casi in cui si prevede di importare solo un BLOB di certificato di chiave pubblica. Il costruttoreX509Certificate2(byte[]) è sicuro per l'uso quando vengono forniti BLOB non PFX non attendibili.
using System.Security.Cryptography.X509Certificates;
public static X509Certificate2 ImportPublicCertificateBlob(byte[] blob)
{
if (X509Certificate2.GetCertContentType(blob) == X509ContentType.Pfx)
{
throw new Exception("PFX blobs are disallowed.");
}
else
{
// Import only after we have confirmed it's not a PFX.
return new X509Certificate2(blob);
}
}
Se è necessario importare un BLOB di certificato chiave privata senza password e si è stabilito che il BLOB è attendibile, è possibile eliminare gli altri controlli di convalida eseguiti dal rilascio della sicurezza del 13 giugno 2023 chiamando un overload del costruttore diverso. Ad esempio, è possibile chiamare l'overload del costruttore che accetta un argomento password stringa e passare null per il valore dell'argomento.
byte[] blobToImport = GetBlobToImport(); // fetch this from a database, config, etc.
// REGRESSION - byte[] ctor performs additional security checks X509Certificate2 certA = new X509Certificate2(blobToImport);
// RECOMMENDED WORKAROUND - different ctor overload suppresses additional security checks X509Certificate2 certB = new X509Certificate2(blobToImport, (string)null);
Opzione 3: modifica o eliminazione della convalida aggiuntiva mediante una variabile di ambiente
Applicabilità: questa opzione si applica solo a tutte le versioni di .NET Framework. Non si applica a .NET 6.0+.
Anche se .NET Framework limita per impostazione predefinita le operazioni di importazione in modo che non siano più di 600.000 iterazioni di una password, questo limite può essere configurato a livello di app o a livello di computer usando una variabile di ambiente. Questo nuovo limite verrà applicato a tutte le chiamate delle API interessate elencate sopra.
Per modificare il limite, impostare la variabile di ambienteCOMPlus_Pkcs12UnspecifiedPasswordIterationLimitsul valore del nuovo limite. Ad esempio, per impostare il limite su 1.000.000 (un milione) iterazioni, impostare la variabile di ambiente come illustrato di seguito.
-
Questo numero controlla il limite di iterazione totale , ovvero la somma del numero di iterazione MAC, del contenuto sicuro crittografato e del numero di iterazione del sacco avvolto. Se hai esportato manualmente un PFX usando un conteggio di iterazione esplicito <iter_count> (ad esempio, tramite openssl pkcs12 -export -iter <iter_count>) e desideri importare il BLOB PFX, imposta questa variabile di ambiente su un valore che sia grande almeno quanto la somma di tutte le iterazioni previste. In pratica, .NET Framework e .NET possono consentire al conteggio totale dell'iterazione di superare leggermente qualsiasi limite esplicito configurato qui.
COMPlus_Pkcs12UnspecifiedPasswordIterationLimit=1000000
Per eliminare completamente i controlli aggiuntivi, impostare la variabile di ambiente sul valore sentinella speciale -1, come illustrato di seguito.
-
⚠️ Avviso: impostare il valore della variabile di ambiente su -1 solo se si è certi che l'applicazione di destinazione non gestisce l'input di certificato non attendibile.
COMPlus_Pkcs12UnspecifiedPasswordIterationLimit=-1
Opzione 4 : modifica o eliminazione della convalida aggiuntiva tramite AppContext
Applicabilità: questa opzione si applica solo a .NET 6.0+. Non si applica a .NET Framework
Anche se .NET limita per impostazione predefinita le operazioni di importazione per non richiedere più di 600.000 iterazioni di una password, questo limite può essere configurato a livello di applicazione utilizzando il parametro AppContext. Questo nuovo limite verrà applicato a tutte le chiamate delle API interessate elencate sopra.
Per modificare il limite, impostare l'opzione AppContext System.Security.Cryptography.Pkcs12UnspecifiedPasswordIterationLimit sul valore del nuovo limite. Ad esempio, per impostare il limite su 1.000.000 (un milione) iterazioni, impostare l'opzione come illustrato di seguito.
-
Questo numero controlla il limite di iterazione totale, ovvero la somma del numero di iterazione MAC, del contenuto sicuro crittografato e del numero di iterazione del sacco avvolto. Se hai esportato manualmente un PFX usando un conteggio di iterazione esplicito <iter_count> (ad esempio, tramite openssl pkcs12 -export -iter <iter_count>) e desideri importare il BLOB PFX, imposta questa variabile di ambiente su un valore che sia grande almeno quanto la somma di tutte le iterazioni previste. In pratica, .NET può consentire al numero totale di iterazioni di superare leggermente qualsiasi limite esplicito configurato qui.
Per impostare l'opzione all'interno del file di progetto dell'applicazione (csproj o vbproj):
<!--
- This switch only works if the current project file represents an application. It has no effect if the current project file represents a shared library.
-->
<ItemGroup>
- <RuntimeHostConfigurationOption Include="System.Security.Cryptography.Pkcs12UnspecifiedPasswordIterationLimit" Value="1000000" />
</ItemGroup>
In alternativa, è possibile inserire un file denominato runtimeconfig.template.json con il contenuto seguente nella stessa directory che contiene il file di progetto dell'applicazione:
{
"configProperties": {
- "System.Security.Cryptography.Pkcs12UnspecifiedPasswordIterationLimit": 1000000
}
}
Per altre informazioni sulla modifica delle impostazioni di configurazione del runtime .NET, vedere la pagina della documentazione Impostazioni di configurazione di Runtime .NET.
Per eliminare completamente i controlli aggiuntivi, impostare l'interruttore di configurazione sul valore sentinella speciale -1, come mostrato di seguito.
⚠️ Avviso: impostare l'opzione AppContext su -1 solo se si è certi che l'applicazione di destinazione non gestisce l'input di certificato non attendibile.
All'interno del file di progetto dell'applicazione (csproj o vbproj):
<!--
- This switch only works if the current project file represents an application. It has no effect if the current project file represents a shared library.
-->
<ItemGroup>
- <RuntimeHostConfigurationOption Include="System.Security.Cryptography.Pkcs12UnspecifiedPasswordIterationLimit" Value="-1" />
</ItemGroup>
Oppure all'interno del file runtimeconfig.template.json:
{
- "configProperties": {
- "System.Security.Cryptography.Pkcs12UnspecifiedPasswordIterationLimit": -1
}
}
Opzione 5 - Modifica o eliminazione della convalida aggiuntiva a livello di computer tramite il Registro di sistema (Solo Windows per .NET Framework)
Applicabilità: questa opzione si applica solo a tutte le versioni di .NET Framework. Non si applica a .NET 6.0+.
Anche se .NET Framework per impostazione predefinita limita le operazioni di importazione per non richiedere più di 600.000 iterazioni di una password, questo limite può essere configurato a livello di computer usando il Registro di sistema HKLM. Questo nuovo limite verrà applicato a tutte le chiamate delle API interessate elencate sopra.
Per modificare il limite, nella chiave del Registro di sistemaHKLM\Software\Microsoft\.NETFrameworkimpostare il valorePkcs12UnspecifiedPasswordIterationLimitsul nuovo limite. Ad esempio, per impostare il limite su 1.000.000 (un milione) iterazioni, eseguire i comandi come illustrato di seguito da un prompt dei comandi con privilegi elevati.
-
Questo numero controlla il limite di iterazione totale , ovvero la somma del numero di iterazione MAC, del contenuto sicuro crittografato e del numero di iterazione del sacco avvolto. Se hai esportato manualmente un PFX usando un conteggio di iterazione esplicito <iter_count> (ad esempio, tramite openssl pkcs12 -export -iter <iter_count>) e desideri importare il BLOB PFX, imposta questo valore del Registro di sistema su un valore che sia grande almeno quanto la somma di tutte le iterazioni previste. In pratica, .NET Framework può consentire al numero totale di iterazioni di superare leggermente qualsiasi limite esplicito configurato qui.
-
L'impostazione del Registro di sistema dipende dall'architettura. Per assicurarsi che le applicazioni osservino il valore configurato indipendentemente dall'architettura di destinazione, ricordarsi di modificare sia i registri a 32 bit che a 64 bit, come illustrato di seguito.
reg add "HKLM\Software\Microsoft\.NETFramework" /v Pkcs12UnspecifiedPasswordIterationLimit /t REG_DWORD /d 1000000 /reg:32 reg add "HKLM\Software\Microsoft\.NETFramework" /v Pkcs12UnspecifiedPasswordIterationLimit /t REG_DWORD /d 1000000 /reg:64
Per eliminare completamente i controlli aggiuntivi, impostare il valore del Registro di sistema su -1 da un prompt dei comandi con privilegi elevati, come illustrato di seguito.
-
⚠️ Avviso: impostare il valore del Registro di sistema su -1 solo se si è certi che i servizi in esecuzione nel computer di destinazione non gestiscono l'input di certificato non attendibile.
-
Per impostare -1 sentinella, utilizzare il tipo di REG_SZ invece del tipo di REG_DWORD. L'impostazione del Registro di sistema dipende dall'architettura. Per assicurarsi che le applicazioni osservino il valore configurato indipendentemente dall'architettura di destinazione, ricordarsi di modificare sia i registri a 32 bit che a 64 bit, come illustrato di seguito.
reg add "HKLM\Software\Microsoft\.NETFramework" /v Pkcs12UnspecifiedPasswordIterationLimit /t REG_SZ /d -1 /reg:32 reg add "HKLM\Software\Microsoft\.NETFramework" /v Pkcs12UnspecifiedPasswordIterationLimit /t REG_SZ /d -1 /reg:64
Per ripristinare le modifiche al Registro di sistema, elimina il valore reg Pkcs12UnspecifiedPasswordIterationLimit da un prompt dei comandi con privilegi elevati.
reg delete "HKLM\Software\Microsoft\.NETFramework" /v Pkcs12UnspecifiedPasswordIterationLimit /reg:32 reg delete "HKLM\Software\Microsoft\.NETFramework" /v Pkcs12UnspecifiedPasswordIterationLimit /reg:64
Note specifiche di Windows
In Windows, i certificati di importazione di .NET Framework tramite la funzione PFXImportCertStore. Questa funzione esegue una convalida specifica, inclusa l'impostazione di limiti specifici per il numero massimo di iterazioni consentite di un BLOB PFX. Questi controlli verranno comunque eseguiti dopo l'importazione PFX. Le. Le variabili di ambiente specifiche di NET e le chiavi del Registro di sistema descritte in precedenza non influiscono sul modo in cui PFXImportCertStore esegue questi controlli.