Remarque : Mise à jour du 22 juin 2023 pour mettre à jour la résolution et les solutions de contournement
Remarque : Révisé le 15 juin 2023 pour mettre à jour le travail autour des options 4 et 5
Fond
Le 13 juin 2023, Microsoft a publié une mise à jour de sécurité pour .NET Framework et .NET qui affecte la façon dont le runtime importe les certificats X.509. Ces modifications peuvent entraîner l’importation du certificat X.509 à lever CryptographicException dans les scénarios où l’importation aurait réussi avant la mise à jour.
Ce document décrit les modifications et les solutions de contournement disponibles pour les applications impactées.
Logiciels concernés
-
.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 affectées
Description de la modification
Avant le 13 juin 2023, modification, lorsque .NET Framework et .NET sont présentés avec un objet blob de certificats binaires pour l’importation, .NET Framework et .NET délèguent généralement la validation et l’importation de l’objet blob au système d’exploitation sous-jacent. Par exemple, sur Windows, .NET Framework et .NET s’appuient généralement sur l’API PFXImportCertStore pour la validation et l’importation.
À compter du 13 juin 2023, modification, lorsque .NET Framework et .NET sont présentés avec un objet blob de certificats binaires pour l’importation, .NET Framework et .NET effectuent dans certains cas une validation supplémentaire avant de remettre l’objet blob au système d’exploitation sous-jacent. Cette validation supplémentaire effectue une série de vérifications heuristiques pour déterminer si le certificat entrant épuiserait les ressources de manière malveillante lors de l’importation. Étant donné qu’il s’agit d’une validation supplémentaire au-delà de ce que le système d’exploitation sous-jacent effectuerait normalement, il peut bloquer les objets blob de certificats qui auraient été importés avec succès avant la modification du 13 juin 2023.
Régressions connues
-
Si un certificat X.509 a été exporté en tant qu’objet blob PFX à l’aide d’un nombre d’itérations de mot de passe exceptionnellement élevé, l’importation de ce certificat peut maintenant échouer. La plupart des fonctionnalités d’exportation de certificats utilisent un nombre d’itérations compris entre 2 000 et 10 000. Une fois la mise à jour de sécurité appliquée, l’importation échoue pour les certificats contenant un nombre d’itérations supérieur à 600 000.
-
Si un certificat X.509 a été exporté à l’aide d’un mot de passe null [par exemple, viaX509Certificate.Export(X509ContentType.Pfx, (string)null)ou leX509Certificate.Export(X509ContentType.Pfx)]sans mot de passe , l’importation de ce certificat peut maintenant échouer.
Remarque : La régression ci-dessus a été traitée dans la mise à jour du 22 juin 2023 décrite dans KB5028608.
-
Si un certificat X.509 a été exporté en tant qu’objet blob PFX à l’aide de la fonctionnalité de Windows pour protéger la clé privée sur un SID, l’importation de ce certificat peut maintenant échouer. Cela aura un impact sur les objets blob PFX créés de la manière suivante :
-
Via l’Assistant Exportation de certificat de Windows et en spécifiant dans l’Assistant que la clé privée doit être protégée pour un utilisateur de domaine ; Ou
-
Via l’applet de commande Export-PfxCertificate de PowerShell où un argument -ProtectTo explicite est fourni ; Ou
-
Via l’utilitaire certutil où un argument -protectto explicite est fourni ; Ou
-
Via l’API PFXExportCertStoreEx où l’indicateur PKCS12_PROTECT_TO_DOMAIN_SIDS est fourni.
-
Solutions de contournement & de résolution
Il existe différentes solutions de contournement, selon que vous souhaitez apporter des modifications ciblées sur des sites d’appel individuels dans votre code, que vous souhaitez modifier le comportement d’une seule application ou que vous souhaitez apporter des modifications à l’échelle de l’ordinateur.
Option 1 (par défaut) - Installer un correctif mis à jour
Remarque : Il s’agit de l’option recommandée, car elle traite les régressions client couramment signalées et ne nécessite aucune modification du code de l’application.
Applicabilité : cette option s’applique à toutes les versions de .NET Framework et .NET.
Ce problème a été résolu dans la mise à jour du 22 juin 2023 décrite dans KB5028608.
Microsoft recommande aux clients qui rencontrent des régressions introduites par la version du 13 juin 2023 d’essayer d’installer ce correctif mis à jour avant d’essayer les solutions de contournement répertoriées plus loin dans ce document.
Option 2 - Modification du site d’appel
Applicabilité : cette option s’applique à toutes les versions de .NET Framework et .NET.
Déterminez si l’objet blob que vous importez est fiable. Par exemple, l’objet blob a-t-il été récupéré à partir d’un emplacement approuvé, comme une base de données ou un fichier de configuration sous votre contrôle, ou a-t-il été fourni via une requête réseau effectuée par un client non authentifié ou non privilégié ?
Microsoft vous recommande vivement de ne pas importer d’objets blob PFX fournis par des clients non authentifiés ou non privilégiés, car ces objets blob peuvent contenir des comportements malveillants d’épuisement des ressources.
Si vous devez importer un objet blob de certificat de clé publique fourni par une partie non approuvée, vous pouvez utiliser le code suivant pour importer en toute sécurité un tel objet blob. Cet exemple de code utilise la méthode GetCertContentType pour déterminer le type sous-jacent de l’objet blob de certificats et rejette les objets blob PFX dans les cas où vous prévoyez uniquement d’importer un objet blob de certificat de clé publique. Le constructeurX509Certificate2(byte[]) peut être utilisé en cas d’utilisation d’objets blob non PFX non approuvés.
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);
}
}
Si vous devez importer un objet blob de certificat de clé privée sans mot de passe et que vous avez déterminé que l’objet blob est fiable, vous pouvez supprimer les vérifications de validation supplémentaires effectuées par la version de sécurité du 13 juin 2023 en appelant une surcharge de constructeur différente. Par exemple, vous pouvez appeler la surcharge de constructeur qui accepte un argument de mot de passe de chaîne et passe la valeur null pour la valeur de l’argument.
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);
Option 3 : modification ou suppression de la validation supplémentaire à l’aide d’une variable d’environnement
Applicabilité : cette option s’applique uniquement à toutes les versions du .NET Framework. Elle ne s’applique pas à .NET 6.0+.
Bien que .NET Framework limite par défaut les opérations d’importation à ne pas prendre plus de 600 000 itérations d’un mot de passe, cette limite peut être configurée à l’échelle de l’application ou de l’ordinateur à l’aide d’une variable d’environnement. Cette nouvelle limite s’applique à tous les appels des API affectées répertoriées ci-dessus.
Pour modifier la limite, définissez la variable d’environnementCOMPlus_Pkcs12UnspecifiedPasswordIterationLimitsur la valeur de la nouvelle limite. Par exemple, pour définir la limite à 1 000 000 itérations (un million), définissez la variable d’environnement comme indiqué ci-dessous.
-
Ce nombre contrôle la limite totale des itérations, qui est la somme du nombre d’itérations MAC, du contenu sécurisé chiffré et du nombre d’itérations du conteneur enveloppé. Si vous avez exporté manuellement un PFX à l’aide d’un nombre d’itérations explicite <iter_count> (par exemple, via openssl pkcs12 -export -iter <iter_count>) et que vous souhaitez importer cet objet blob PFX, définissez cette variable d’environnement sur une valeur au moins égale à la somme de toutes les itérations attendues. Dans la pratique, .NET Framework et .NET peuvent autoriser le nombre total d’itérations à dépasser légèrement toute limite explicite configurée ici.
COMPlus_Pkcs12UnspecifiedPasswordIterationLimit=1000000
Pour supprimer entièrement les vérifications supplémentaires, définissez la variable d’environnement sur la valeur sentinelle spéciale -1, comme indiqué ci-dessous.
-
⚠️ Avertissement : définissez la valeur de la variable d’environnement sur -1 uniquement si vous êtes certain que l’application cible ne gère pas l’entrée de certificat non approuvé.
COMPlus_Pkcs12UnspecifiedPasswordIterationLimit=-1
Option 4 : Modification ou suppression de la validation supplémentaire à l’aide d’AppContext
Applicabilité : cette option s’applique uniquement à .NET 6.0+. Elle ne s’applique pas au .NET Framework
Bien que .NET limite par défaut les opérations d’importation à ne pas prendre plus de 600 000 itérations d’un mot de passe, cette limite peut être configurée à l’échelle de l’application à l’aide du commutateur AppContext. Cette nouvelle limite s’applique à tous les appels des API affectées répertoriées ci-dessus.
Pour modifier la limite, définissez le commutateur AppContext System.Security.Cryptography.Pkcs12UnspecifiedPasswordIterationLimit sur la valeur de la nouvelle limite. Par exemple, pour définir la limite sur 1 000 000 itérations (un million), définissez le commutateur comme indiqué ci-dessous.
-
Ce nombre contrôle la limite totale des itérations, qui est la somme du nombre d’itérations MAC, du contenu sécurisé chiffré et du nombre d’itérations du conteneur enveloppé. Si vous avez exporté manuellement un PFX à l’aide d’un nombre d’itérations explicite <iter_count> (par exemple, via openssl pkcs12 -export -iter <iter_count>) et que vous souhaitez importer cet objet blob PFX, définissez cette variable d’environnement sur une valeur au moins égale à la somme de toutes les itérations attendues. Dans la pratique, .NET peut autoriser le nombre total d’itérations à dépasser légèrement toute limite explicite configurée ici.
Pour définir le commutateur dans le fichier projet de votre application (.csproj ou .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>
Vous pouvez également placer un fichier nommé runtimeconfig.template.json avec le contenu suivant dans le même répertoire qui contient le fichier projet de votre application :
{
"configProperties": {
- "System.Security.Cryptography.Pkcs12UnspecifiedPasswordIterationLimit": 1000000
}
}
Pour plus d’informations sur la modification des paramètres de configuration du runtime .NET, consultez la page de documentation Paramètres de configuration du runtime .NET.
Pour supprimer entièrement les vérifications supplémentaires, définissez le commutateur de configuration avec la valeur sentinelle spéciale -1, comme indiqué ci-dessous.
⚠️ Avertissement : définissez le commutateur AppContext sur -1 uniquement si vous êtes certain que l’application cible ne gère pas l’entrée de certificat non approuvé.
Dans le fichier projet de l’application (.csproj ou .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>
Ou dans le fichier runtimeconfig.template.json :
{
- "configProperties": {
- "System.Security.Cryptography.Pkcs12UnspecifiedPasswordIterationLimit": -1
}
}
Option 5 : Modification ou suppression de la validation supplémentaire à l’échelle de l’ordinateur via le Registre (Windows uniquement pour .NET Framework)
Applicabilité : cette option s’applique uniquement à toutes les versions du .NET Framework. Elle ne s’applique pas à .NET 6.0+.
Bien que .NET Framework limite par défaut les opérations d’importation à ne pas prendre plus de 600 000 itérations d’un mot de passe, cette limite peut être configurée à l’échelle de l’ordinateur à l’aide du registre HKLM. Cette nouvelle limite s’applique à tous les appels des API affectées répertoriées ci-dessus.
Pour modifier la limite, sous la clé de RegistreHKLM\Software\Microsoft\.NETFramework, définissez la valeurPkcs12UnspecifiedPasswordIterationLimitsur la nouvelle limite. Par exemple, pour définir la limite à 1 000 000 itérations (un million), exécutez les commandes comme indiqué ci-dessous à partir d’une invite de commandes avec élévation de privilèges.
-
Ce nombre contrôle la limite totale des itérations, qui est la somme du nombre d’itérations MAC, du contenu sécurisé chiffré et du nombre d’itérations du conteneur enveloppé. Si vous avez exporté manuellement un PFX à l’aide d’un nombre d’itérations explicite <iter_count> (par exemple, via openssl pkcs12 -export -iter <iter_count>) et que vous souhaitez importer cet objet blob PFX, définissez cette valeur de Registre sur une valeur au moins égale à la somme de toutes les itérations attendues. Dans la pratique, .NET Framework peut autoriser le nombre total d’itérations à dépasser légèrement toute limite explicite configurée ici.
-
Le paramètre de Registre dépend de l’architecture. Pour vous assurer que les applications respectent votre valeur configurée quelle que soit leur architecture cible, n’oubliez pas de modifier les registres 32 bits et 64 bits, comme indiqué ci-dessous.
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
Pour supprimer entièrement les vérifications supplémentaires, définissez la valeur de Registre sur -1 à partir d’une invite de commandes avec élévation de privilèges, comme indiqué ci-dessous.
-
⚠️ Avertissement : définissez la valeur de Registre sur -1 uniquement si vous êtes certain que les services en cours d’exécution sur l’ordinateur cible ne gèrent pas l’entrée de certificat non approuvé.
-
Pour définir la sentinelle -1, utilisez le type REG_SZ au lieu du type REG_DWORD. Le paramètre de Registre dépend de l’architecture. Pour vous assurer que les applications respectent votre valeur configurée quelle que soit leur architecture cible, n’oubliez pas de modifier les registres 32 bits et 64 bits, comme indiqué ci-dessous.
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
Pour annuler les modifications apportées au Registre, supprimez la valeur reg Pkcs12UnspecifiedPasswordIterationLimit d’une invite de commandes avec élévation de privilèges.
reg delete "HKLM\Software\Microsoft\.NETFramework" /v Pkcs12UnspecifiedPasswordIterationLimit /reg:32 reg delete "HKLM\Software\Microsoft\.NETFramework" /v Pkcs12UnspecifiedPasswordIterationLimit /reg:64
Notes spécifiques à Windows
Sur Windows, .NET Framework importez des certificats via la fonction PFXImportCertStore. Cette fonction effectue sa propre validation, notamment en plaçant ses propres limites sur le nombre maximal d’itérations autorisées d’un objet blob PFX. Ces vérifications ont toujours lieu lors de l’importation PFX. Lla. Les variables d’environnement spécifiques à NET et les clés de Registre décrites ci-dessus n’ont pas d’impact sur la façon dont PFXImportCertStore effectue ces vérifications.