Applies To.NET

Nota: Revista em 22 de junho de 2023 para atualizar resolução e soluções

Nota: Revista a 15 de junho de 2023 para atualizar o trabalho em torno das opções 4 e 5 

Fundo

A 13 de junho de 2023, a Microsoft lançou uma atualização de segurança para .NET Framework e .NET que afeta a forma como o runtime importa certificados X.509. Estas alterações podem fazer com que a importação do certificado X.509 deite CryptographicException em cenários em que a importação teria sido concluída com êxito antes da atualização.

Este documento descreve as alterações e soluções disponíveis para aplicações afetadas.

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 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 normalmente delegariam a validação e importação do blob para o SO 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 irão, em algumas circunstâncias, efetuar validação adicional antes de entregar o blob ao SO subjacente. Esta validação adicional efetua uma série de verificações heurísticas para determinar se o certificado de entrada esgotaria maliciosamente os recursos após a importação. Uma vez que se trata de uma validação adicional para além do que o SO subjacente teria normalmente um desempenho normal, pode bloquear os blobs de certificados que teriam sido importados com êxito antes da alteração de 13 de junho de 2023.

Regressões conhecidas

  1. Se um certificado X.509 tiver sido exportado como um blob PFX com uma contagem de iteração de palavras-passe invulgarmente elevada, esse certificado pode agora não conseguir importar. A maioria das instalações de exportação de certificados utiliza uma contagem de iteração entre 2000 e 10 000. Após a aplicação da atualização de segurança, a importação falhará para certificados que contenham uma contagem de iteração superior a 600 000.

  2. Se um certificado X.509 tiver sido exportado com uma palavra-passe nula [por exemplo, através deX509Certificate.Export(X509ContentType.Pfx, (string)null)ou doX509Certificate.Export(X509ContentType.Pfx)]sem palavra-passe, esse certificado pode agora não conseguir importar.  

    Nota: A regressão acima foi abordada na Atualização de 22 de junho de 2023 abordada na atualização KB5028608.

  3. Se um certificado X.509 tiver sido exportado como um blob PFX com a capacidade do Windows de proteger a chave privada para um SID, esse certificado pode agora não ser importado. Isto afetará os blobs PFX criados das seguintes formas:

    • Através do Assistente de Exportação de Certificados do Windows e especificando no assistente que a chave privada deve ser protegida para um utilizador de domínio; ou

    • Através do cmdlet Export-PfxCertificate do PowerShell em que é fornecido um argumento de -ProtectTo explícito; ou

    • Através do utilitário certutil onde é fornecido um argumento de -protectto explícito; ou

    • Através da API PFXExportCertStoreEx , onde é fornecido o sinalizador PKCS12_PROTECT_TO_DOMAIN_SIDS.

Soluções de Resolução &

Existem várias soluções alternativas, consoante pretenda efetuar alterações direcionadas em sites de chamadas individuais no seu código ou se pretende alterar o comportamento de uma única aplicação ou se pretende efetuar alterações ao nível do computador.

Opção 1 (preferencial) – Instalar um patch atualizado

Nota: Esta é a opção preferencial, uma vez que aborda regressões de clientes frequentemente comunicadas e não requer alterações de código à aplicação.

Aplicabilidade: esta opção aplica-se a todas as versões do .NET Framework e .NET.

Este problema foi resolvido na Atualização de 22 de junho de 2023 abordada na atualização KB5028608.

A Microsoft recomenda que os clientes com regressões introduzidas até 13 de junho de 2023 tentem instalar este patch atualizado antes de tentarem as soluções listadas mais à frente neste documento.

Opção 2 – Modificar o site de chamadas

Aplicabilidade: esta opção aplica-se a todas as versões do .NET Framework e .NET.

Considere se o blob que está a importar é fidedigno. Por exemplo, o blob foi obtido a partir de uma localização fidedigna, como uma base de dados ou um ficheiro de configuração sob o seu controlo, ou foi fornecido através de um pedido de rede feito por um cliente não autenticado ou sem privilégios?

A Microsoft recomenda vivamente que não importe blobs PFX fornecidos por clientes não autenticados ou sem privilégios, uma vez que estes blobs podem conter comportamentos de esgotamento de recursos maliciosos.

Se precisar de importar um blob de certificado de chave pública fornecido por uma parte não fidedigno, pode utilizar o seguinte código para importar esse blob em segurança. Este código de exemplo utiliza o método GetCertContentType para determinar qual é o tipo subjacente do blob de certificados e rejeita blobs PFX nos casos em que apenas espera importar um blob de certificado de chave pública. O construtorX509Certificate2(byte[]) é seguro para utilização quando são fornecidos blobs não PFX não fidedignos.

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 precisar de importar um blob de certificado de chave privada sem palavra-passe e tiver determinado que o blob é fidedigno, pode suprimir as verificações de validação adicionais efetuadas até 13 de junho de 2023, versão de segurança ao chamar uma sobrecarga de construtor diferente. Por exemplo, pode chamar a sobrecarga do construtor, que aceita um argumento de palavra-passe de cadeia e transmite 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 com uma variável de ambiente

Aplicabilidade: esta opção aplica-se apenas a todas as versões do .NET Framework.  Não se aplica ao .NET 6.0+.

Embora, por predefinição, .NET Framework limitar as operações de importação para não demorar mais de 600 000 iterações de uma palavra-passe, este limite pode ser configurado em toda a aplicação ou em toda a máquina utilizando uma variável de ambiente. Este novo limite será aplicado a todas as invocações das APIs Afetadas listadas acima.

Para alterar o limite, defina a variável de ambienteCOMPlus_Pkcs12UnspecifiedPasswordIterationLimitpara o valor do que deve ser o novo limite. Por exemplo, para definir o limite para 1000 000 (um milhão) iterações, defina a variável de ambiente, conforme mostrado abaixo.

  • Este número controla o limite total de iteração, que é a soma da contagem de iteração MAC, os conteúdos seguros encriptados e a contagem de iteração do saco envolto. Se tiver exportado manualmente um PFX com uma contagem de iteração explícita <iter_count> (por exemplo, através de openssl pkcs12 -export -iter <iter_count>) e quiser importar esse blob PFX, defina esta variável de ambiente para 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 para o valor de sentinel especial -1, conforme mostrado abaixo.

  • ⚠️ Aviso: defina apenas o valor da variável de ambiente como -1 se tiver a certeza de que a aplicação de destino não está a processar entradas de certificados não fidedignos.

COMPlus_Pkcs12UnspecifiedPasswordIterationLimit=-1

Opção 4 – Modificar ou suprimir a validação adicional com o AppContext

Aplicabilidade: esta opção aplica-se apenas ao .NET 6.0+.  Não se aplica a .NET Framework

Embora, por predefinição, as operações de importação de limite de .NET não levem mais de 600 000 iterações de uma palavra-passe, este limite pode ser configurado em toda a aplicação com o comutador AppContext. Este novo limite será aplicado a todas as invocações das APIs Afetadas listadas acima.

Para alterar o limite, defina o comutador AppContext System.Security.Cryptography.Pkcs12UnspecifiedPasswordIterationLimit como o valor do novo limite. Por exemplo, para definir o limite para 1000 000 (um milhão) iterações, defina o comutador conforme mostrado abaixo.

  • Este número controla o limite total de iteração, que é a soma da contagem de iteração MAC, os conteúdos seguros encriptados e a contagem de iteração do saco envolto. Se tiver exportado manualmente um PFX com uma contagem de iteração explícita <iter_count> (por exemplo, através de openssl pkcs12 -export -iter <iter_count>) e quiser importar esse blob PFX, defina esta variável de ambiente para 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 o comutador no ficheiro de projeto da sua aplicação (.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>

Em alternativa, pode colocar um ficheiro com o nome runtimeconfig.template.json com os seguintes conteúdos no mesmo diretório que contém o ficheiro de projeto da sua aplicação:

{

     "configProperties": {

  • "System.Security.Cryptography.Pkcs12UnspecifiedPasswordIterationLimit": 1000000

      }

}

Para obter mais informações sobre como alterar as definições de configuração do runtime do .NET, veja a página de documentação .NET Runtime configuration settings (Definições de configuração do Runtime do .NET).

Para suprimir totalmente as verificações adicionais, defina o parâmetro de configuração do valor especial sentinel -1, conforme mostrado abaixo.

⚠️ Aviso: defina apenas o comutador AppContext para -1 se tiver a certeza de que a aplicação de destino não está a processar entradas de certificado não fidedignos.

No ficheiro de projeto da aplicação (.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 ficheiro runtimeconfig.template.json:

{

  • "configProperties": { 
  •     "System.Security.Cryptography.Pkcs12UnspecifiedPasswordIterationLimit": -1

     }

}

Opção 5 – Modificar ou suprimir a máquina de validação adicional em todo o registo (apenas Windows para .NET Framework)

Aplicabilidade: esta opção aplica-se apenas a todas as versões do .NET Framework.  Não se aplica ao .NET 6.0+.

Embora .NET Framework, por predefinição, limitar as operações de importação para não utilizar mais de 600 000 iterações de uma palavra-passe, este limite pode ser configurado em todo o computador com o registo HKLM. Este novo limite será aplicado a todas as invocações das APIs Afetadas listadas acima.

Para alterar o limite, na chave de registoHKLM\Software\Microsoft\.NETFramework, defina o valorPkcs12UnspecifiedPasswordIterationLimitpara qual deve ser o novo limite. Por exemplo, para definir o limite para 1000 000 (um milhão) iterações, execute os comandos conforme mostrado abaixo a partir de uma linha de comandos elevada.

  • Este número controla o limite total de iteração, que é a soma da contagem de iteração MAC, os conteúdos seguros encriptados e a contagem de iteração do saco envolto. Se tiver exportado manualmente um PFX com uma contagem de iteração explícita <iter_count> (por exemplo, através de openssl pkcs12 -export -iter <iter_count>) e quiser importar esse blob PFX, defina este valor de registo para 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 definição do registo é dependente da arquitetura. Para garantir que as aplicações observam o valor configurado independentemente da arquitetura de destino, lembre-se de modificar os registos de 32 bits e de 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 registo como -1 a partir de uma linha de comandos elevada, conforme mostrado abaixo.

  • ⚠️ Aviso: defina apenas o valor do registo como -1 se tiver a certeza de que os serviços em execução no computador de destino não estão a processar entradas de certificados não fidedignos.

  • Para definir o sentinel -1, utilize o tipo de REG_SZ em vez do tipo de REG_DWORD. A definição do registo é dependente da arquitetura. Para garantir que as aplicações observam o valor configurado independentemente da arquitetura de destino, lembre-se de modificar os registos de 32 bits e de 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 registo, elimine o valor do registo Pkcs12UnspecifiedPasswordIterationLimit de uma linha de comandos elevada.

reg delete "HKLM\Software\Microsoft\.NETFramework" /v Pkcs12UnspecifiedPasswordIterationLimit /reg:32 reg delete "HKLM\Software\Microsoft\.NETFramework" /v Pkcs12UnspecifiedPasswordIterationLimit /reg:64

Notas específicas do Windows

No Windows, .NET Framework importar certificados através da função PFXImportCertStore. Esta função executa a sua própria validação, incluindo a colocação dos seus próprios limites na contagem máxima de iteração permitido de um blob PFX. Estas verificações continuarão a ocorrer após a importação de PFX. O . As variáveis de ambiente específicas do NET e as chaves de registo descritas acima não afetam a forma como o PFXImportCertStore efetua estas verificações.

Precisa de mais ajuda?

Quer mais opções?

Explore os benefícios da subscrição, navegue em cursos de formação, saiba como proteger o seu dispositivo e muito mais.

As comunidades ajudam-no a colocar e a responder perguntas, a dar feedback e a ouvir especialistas com conhecimentos abrangentes.