Observação: Revisado em 22 de junho de 2023 para atualizar a resolução e soluções alternativas
Observação: Revisado em 15 de junho de 2023 para atualizar o trabalho em torno das opções 4 e 5
Fundo
Em 13 de junho de 2023, a Microsoft lançou uma atualização de segurança para .NET Framework e .NET que afeta como o runtime importa certificados X.509. Essas alterações podem fazer com que a importação de certificado X.509 lance CryptographicException em cenários em que a importação teria sido bem-sucedida antes da atualização.
Este documento descreve as soluções alternativas e de alteração disponíveis para aplicativos afetados.
Software afetado
-
.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
APIs afetadas
Descrição da alteração
Antes da alteração de 13 de junho de 2023, quando .NET Framework e .NET são apresentados com um blob de certificado binário para importação, .NET Framework e .NET normalmente delegariam a validação e a importação do blob para o sistema operacional subjacente. Por exemplo, no Windows, .NET Framework e .NET normalmente dependem da API PFXImportCertStore para validação e importação.
A partir de 13 de junho de 2023, a alteração, quando .NET Framework e .NET são apresentados com um blob de certificado binário para importação, .NET Framework e .NET executarão em algumas circunstâncias uma validação adicional antes de entregar o blob ao sistema operacional subjacente. Essa validação adicional executa uma série de verificações heurísticas para determinar se o certificado de entrada esgotaria maliciosamente os recursos após a importação. Como essa é uma validação adicional além do que o sistema operacional subjacente normalmente executaria, ela pode bloquear blobs de certificado que teriam importado com êxito antes da alteração de 13 de junho de 2023.
Regressões conhecidas
-
Se um certificado X.509 tiver sido exportado como um blob PFX usando uma contagem de iteração de senha extraordinariamente alta, esse certificado poderá agora não importar. A maioria das instalações de exportação de certificados usa uma contagem de iteração entre 2.000 e 10.000. Depois que a atualização de segurança for aplicada, a importação falhará para certificados que contenham uma contagem de iteração maior que 600.000.
-
Se um certificado X.509 tiver sido exportado usando uma senha nula [por exemplo, viaX509Certificate.Export(X509ContentType.Pfx, (string)null)ou oX509Certificate.Export(X509ContentType.Pfx)]sem senha , esse certificado poderá agora não importar.
Observação: A regressão acima foi abordada na Atualização de 22 de junho de 2023 discutida no KB5028608.
-
Se um certificado X.509 tiver sido exportado como um blob PFX usando a capacidade do Windows para proteger a chave privada para um SID, esse certificado poderá agora não importar. Isso afetará os blobs PFX criados das seguintes maneiras:
-
Por meio do Assistente de Exportação de Certificados do Windows e especificando no assistente que a chave privada deve ser protegida para um usuário de domínio; Ou
-
Por meio do cmdlet Export-PfxCertificate do PowerShell em que um argumento -ProtectTo explícito é fornecido; Ou
-
Por meio do utilitário certutil em que um argumento -protectto explícito é fornecido; Ou
-
Por meio da API PFXExportCertStoreEx , onde o sinalizador PKCS12_PROTECT_TO_DOMAIN_SIDS é fornecido.
-
Solução & Soluções Alternativas
Existem várias soluções alternativas, dependendo se você deseja fazer alterações direcionadas em sites de chamadas individuais dentro do código ou se deseja alterar o comportamento de um único aplicativo ou se deseja fazer alterações em todo o computador.
Opção 1 (preferencial) – Instalar um patch atualizado
Observação: Essa é a opção preferida, pois trata de regressões de cliente comumente relatadas e não requer alterações de código no aplicativo.
Aplicabilidade: essa opção se aplica a todas as versões do .NET Framework e do .NET.
Esse problema foi resolvido na Atualização de 22 de junho de 2023 discutida no KB5028608.
A Microsoft recomenda que os clientes que estão experimentando regressões introduzidas até 13 de junho de 2023, a versão tente instalar este patch atualizado antes de tentar as soluções alternativas listadas posteriormente neste documento.
Opção 2 – Modificando o site de chamadas
Aplicabilidade: essa opção se aplica a todas as versões do .NET Framework e do .NET.
Considere se o blob que você está importando é confiável. Por exemplo, o blob foi recuperado de um local confiável, como um banco de dados ou um arquivo de configuração sob seu controle, ou foi fornecido por meio de uma solicitação de rede feita por um cliente não autenticado ou desprivilegiado?
A Microsoft recomenda fortemente que você não importe blobs PFX fornecidos a você por clientes não autenticados ou nãoprivilegiados, pois esses blobs podem conter comportamentos de esgotamento de recursos mal-intencionados.
Se você precisar importar um blob de certificado de chave pública dado a você por uma parte não confiável, você pode usar o código a seguir para importar com segurança esse blob. Este código de exemplo usa o método GetCertContentType para determinar qual é o tipo subjacente do blob de certificado e rejeita blobs PFX nos casos em que você só espera importar um blob de certificado de chave pública. O construtorX509Certificate2(byte[]) é seguro para uso quando dado blobs não PFX não confiáveis.
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 você precisar importar um blob de certificado de chave privada sem senha e tiver determinado que o blob é confiável, você pode suprimir as verificações de validação adicionais executadas até 13 de junho de 2023, versão de segurança chamando uma sobrecarga de construtor diferente. Por exemplo, você pode chamar a sobrecarga do construtor que aceita um argumento de senha de cadeia de caracteres e passar nulo para o valor do argumento.
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);
Opção 3 – Modificar ou suprimir a validação adicional usando uma variável de ambiente
Aplicabilidade: essa opção se aplica a todas as versões de .NET Framework somente. Ele não se aplica ao .NET 6.0+.
Embora .NET Framework por padrão limitar as operações de importação para não levar mais de 600.000 iterações de uma senha, esse limite pode ser configurado em uma base de todo o aplicativo ou em todo o computador usando uma variável de ambiente. Esse novo limite se aplicará a todas as invocações das APIs afetadas listadas acima.
Para alterar o limite, defina a variável de ambienteCOMPlus_Pkcs12UnspecifiedPasswordIterationLimitpara o valor de qual novo limite deve ser. Por exemplo, para definir o limite como 1.000.000 iterações (um milhão), defina a variável de ambiente conforme mostrado abaixo.
-
Esse número controla o limite total de iteração, que é a soma da contagem de iteração MAC, o conteúdo seguro criptografado e a contagem de iteração do saco encoberto. Se você tiver exportado manualmente um PFX usando uma contagem de iteração explícita <iter_count> (por exemplo, via openssl pkcs12 -export -iter <iter_count>) e deseja importar esse blob PFX, defina essa variável de ambiente como um valor pelo menos tão grande quanto a soma de todas as iterações esperadas. Na prática, .NET Framework e .NET podem permitir que a contagem total de iteração exceda ligeiramente qualquer limite explícito configurado aqui.
COMPlus_Pkcs12UnspecifiedPasswordIterationLimit=1000000
Para suprimir totalmente as verificações adicionais, defina a variável de ambiente como o valor do sentinela especial -1, conforme mostrado abaixo.
-
⚠️ Aviso: apenas defina o valor da variável de ambiente como -1 se você tiver certeza de que o aplicativo de destino não está lidando com entradas de certificado não confiáveis.
COMPlus_Pkcs12UnspecifiedPasswordIterationLimit=-1
Opção 4 – Modificar ou suprimir a validação adicional usando o AppContext
Aplicabilidade: essa opção se aplica somente ao .NET 6.0+. Não se aplica a .NET Framework
Embora o .NET por padrão limite as operações de importação não levem mais de 600.000 iterações de uma senha, esse limite pode ser configurado em todo o aplicativo usando a opção AppContext. Esse novo limite se aplicará a todas as invocações das APIs afetadas listadas acima.
Para alterar o limite, defina a opção AppContext System.Security.Cryptography.Pkcs12UnspecifiedPasswordIterationLimit como o valor de qual novo limite deve ser. Por exemplo, para definir o limite como 1.000.000 iterações (um milhão), defina a opção conforme mostrado abaixo.
-
Esse número controla o limite total de iteração, que é a soma da contagem de iteração MAC, o conteúdo seguro criptografado e a contagem de iteração do saco encoberto. Se você tiver exportado manualmente um PFX usando uma contagem de iteração explícita <iter_count> (por exemplo, via openssl pkcs12 -export -iter <iter_count>) e deseja importar esse blob PFX, defina essa variável de ambiente como um valor pelo menos tão grande quanto a soma de todas as iterações esperadas. Na prática, o .NET pode permitir que a contagem total de iteração exceda ligeiramente qualquer limite explícito configurado aqui.
Para definir a opção dentro do arquivo de projeto do aplicativo (.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>
Como alternativa, você pode colocar um arquivo chamado runtimeconfig.template.json com o seguinte conteúdo no mesmo diretório que contém o arquivo de projeto do aplicativo:
{
"configProperties": {
- "System.Security.Cryptography.Pkcs12UnspecifiedPasswordIterationLimit": 1000000
}
}
Para obter mais informações sobre como alterar as configurações de runtime do .NET, consulte a página de documentação .NET Runtime configurações de configuração.
Para suprimir totalmente as verificações adicionais, defina a configuração alternar o valor do sentinela especial -1, conforme mostrado abaixo.
⚠️ Aviso: apenas defina a opção AppContext como -1 se você tiver certeza de que o aplicativo de destino não está lidando com entradas de certificado não confiáveis.
No arquivo de projeto do aplicativo (.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 no arquivo runtimeconfig.template.json:
{
- "configProperties": {
- "System.Security.Cryptography.Pkcs12UnspecifiedPasswordIterationLimit": -1
}
}
Opção 5 – Modificar ou suprimir o computador de validação adicional por meio do registro (somente windows para .NET Framework)
Aplicabilidade: essa opção se aplica a todas as versões de .NET Framework somente. Ele não se aplica ao .NET 6.0+.
Embora .NET Framework por padrão limitar as operações de importação para não levar mais de 600.000 iterações de uma senha, esse limite pode ser configurado em todo o computador usando o registro HKLM. Esse novo limite se aplicará a todas as invocações das APIs afetadas listadas acima.
Para alterar o limite, na chave do registroHKLM\Software\Microsoft\.NETFramework, defina o valorPkcs12UnspecifiedPasswordIterationLimitcomo o novo limite deve ser. Por exemplo, para definir o limite como 1.000.000 iterações (um milhão), execute os comandos conforme mostrado abaixo de um prompt de comando elevado.
-
Esse número controla o limite total de iteração, que é a soma da contagem de iteração MAC, o conteúdo seguro criptografado e a contagem de iteração do saco encoberto. Se você tiver exportado manualmente um PFX usando uma contagem de iteração explícita <iter_count> (por exemplo, via openssl pkcs12 -export -iter <iter_count>) e deseja importar esse blob PFX, defina esse valor de registro como um valor pelo menos tão grande quanto a soma de todas as iterações esperadas. Na prática, .NET Framework pode permitir que a contagem total de iteração exceda ligeiramente qualquer limite explícito configurado aqui.
-
A configuração do registro depende da arquitetura. Para garantir que os aplicativos observem o valor configurado independentemente da arquitetura de destino, lembre-se de modificar os registros de 32 bits e 64 bits, conforme mostrado abaixo.
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
Para suprimir totalmente as verificações adicionais, defina o valor do registro como -1 de um prompt de comando elevado, conforme mostrado abaixo.
-
⚠️ Aviso: apenas defina o valor do registro como -1 se você tiver certeza de que os serviços em execução no computador de destino não estão lidando com entradas de certificado não confiáveis.
-
Para definir o sentinela -1, use o tipo REG_SZ em vez do tipo REG_DWORD. A configuração do registro depende da arquitetura. Para garantir que os aplicativos observem o valor configurado independentemente da arquitetura de destino, lembre-se de modificar os registros de 32 bits e 64 bits, conforme mostrado abaixo.
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
Para reverter as alterações do registro, exclua o valor de reg Pkcs12UnspecifiedPasswordIterationLimit de um prompt de comando elevado.
reg delete "HKLM\Software\Microsoft\.NETFramework" /v Pkcs12UnspecifiedPasswordIterationLimit /reg:32 reg delete "HKLM\Software\Microsoft\.NETFramework" /v Pkcs12UnspecifiedPasswordIterationLimit /reg:64
Anotações específicas do Windows
No Windows, .NET Framework importar certificados por meio da função PFXImportCertStore. Essa função executa sua própria validação, incluindo colocar seus próprios limites na contagem máxima de iteração permitida de um blob PFX. Essas verificações ainda ocorrerão após a importação do PFX. O. As variáveis de ambiente e as chaves de registro específicas do NET descritas acima não afetam como o PFXImportCertStore executa essas verificações.