Applies To.NET

Notă: Revizuit la 22 iunie 2023 pentru a actualiza rezoluția și soluțiile

Notă: Revizuit la 15 iunie 2023 pentru a actualiza lucrul la opțiunile 4 și 5 

Fundal

Pe 13 iunie 2023, Microsoft a lansat o actualizare de securitate pentru .NET Framework și .NET, care afectează modul în care runtime importă certificate X.509. Aceste modificări pot face ca importul certificatului X.509 să lanseze CryptographicException în scenarii în care importul ar fi reușit înainte de actualizare.

Acest document descrie modificările și soluțiile disponibile pentru aplicațiile afectate.

Software afectat

  • .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-uri afectate

Descrierea modificării

Înainte de 13 iunie 2023, modificarea, atunci când .NET Framework și .NET sunt prezentate cu un blob de certificat binar pentru import, .NET Framework și .NET ar delega de obicei validarea și importul blobului în sistemul de operare subiacent. De exemplu, în Windows, .NET Framework și .NET se bazează de obicei pe API-ul PFXImportCertStore pentru validare și import.

Începând cu data de 13 iunie 2023, modificarea, atunci când .NET Framework și .NET sunt prezentate cu un blob de certificat binar pentru import, .NET Framework și .NET vor efectua, în unele circumstanțe, o validare suplimentară înainte de a înmâna blobul sistemului de operare subiacent. Această validare suplimentară efectuează o serie de verificări euristice pentru a determina dacă certificatul de intrare ar epuiza cu rea intenție resursele la import. Deoarece aceasta este o validare suplimentară , dincolo de ceea ce ar efectua în mod normal sistemul de operare subiacent, acesta poate bloca bloburile de certificate care ar fi importat cu succes înainte de modificarea din 13 iunie 2023.

Regresii cunoscute

  1. Dacă un certificat X.509 a fost exportat ca blob PFX utilizând un număr neobișnuit de mare de iterație de parole, acel certificat poate să nu reușească acum să importe. Majoritatea facilităților de export de certificate utilizează un număr de iterație undeva între 2.000 și 10.000. După ce se aplică actualizarea de securitate, importul nu va reuși pentru certificatele care conțin un număr de iterații mai mare de 600.000.

  2. Dacă un certificat X.509 a fost exportat utilizând o parolă nulă [de exemplu, prinX509Certificate.Export(X509ContentType.Pfx, (string)null)sauX509Certificate.Export(X509ContentType.Pfx)]fără parolă , este posibil ca acel certificat să nu reușească acum să importe.  

    Notă: Regresia de mai sus a fost abordată în actualizarea din 22 iunie 2023 discutată în KB5028608.

  3. Dacă un certificat X.509 a fost exportat ca blob PFX utilizând capacitatea Windows de a proteja cheia privată pe un SID, acel certificat poate să nu reușească acum să importe. Acest lucru va afecta bloburile PFX create în următoarele maniere:

    • Prin Expertul de export certificate Windows și specificând în expert că cheia privată ar trebui să fie protejată pentru un utilizator de domeniu; Sau

    • Prin cmdletul Export-PfxCertificate al PowerShell, unde este furnizat un argument -ProtectTo explicit; Sau

    • Prin intermediul utilitarului certutil în care se furnizează un argument -protectto explicit; Sau

    • Prin API-ul PFXExportCertStoreEx unde este furnizat semnalizatorul PKCS12_PROTECT_TO_DOMAIN_SIDS.

Soluții de rezolvare &

Există diverse soluții, în funcție de ceea ce doriți să faceți: să efectuați modificări țintite la site-uri de apel individuale în cadrul codului, dacă doriți să modificați comportamentul unei singure aplicații sau doriți să efectuați modificări la nivel de computer.

Opțiunea 1 (preferată) - Instalați o corecție actualizată

Notă: Aceasta este opțiunea preferată, deoarece tratează regresiile raportate frecvent ale clienților și nu necesită modificări de cod în aplicație.

Aplicabilitate: Această opțiune se aplică tuturor versiunilor de .NET Framework și .NET.

Această problemă a fost abordată în actualizarea din 22 iunie 2023 discutată în KB5028608.

Microsoft recomandă clienților care se confruntă cu regresii introduse de lansarea din 13 iunie 2023 să încerce să instaleze această corecție actualizată înainte de a încerca soluțiile listate mai târziu în acest document.

Opțiunea 2 - Modificarea site-ului de apel

Aplicabilitate: Această opțiune se aplică tuturor versiunilor de .NET Framework și .NET.

Gândiți-vă dacă blobul pe care îl importați este de încredere. De exemplu, blobul a fost regăsit dintr-o locație de încredere, cum ar fi o bază de date sau un fișier de configurare sub controlul dvs. sau a fost furnizat printr-o solicitare de rețea făcută de un client neautentificat sau neprivilegiat?

Microsoft recomandă insistent să nu importați bloburi PFX furnizate de clienți neautentificați sau neprivilegiți, deoarece aceste bloburi ar putea conține comportamente rău intenționate de epuizare a resurselor.

Dacă trebuie să importați un blob de certificat de cheie publică pe care vi l-a dat o parte care nu este de încredere, puteți utiliza următorul cod pentru a importa în siguranță un astfel de blob. Acest cod eșantion utilizează metoda GetCertContentType pentru a determina care este tipul subiacent al blobului de certificat și respinge blobul PFX în cazurile în care vă așteptați să importați doar un blob de certificat de cheie publică. ConstructorulX509Certificate2(byte[]) este sigur pentru utilizare atunci când sunt date blobs non-PFX care nu sunt de încredere.

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);
    }
} 

Dacă trebuie să importați un blob de certificat de cheie privată fără parolă și ați stabilit că blobul este de încredere, puteți suprima verificările de validare suplimentare efectuate de 13 iunie 2023, prin apelarea altei supraîncărcări de constructor. De exemplu, puteți să apelați supraîncărcarea constructorului care acceptă un argument șir de parolă și să transmiteți valoarea nulă pentru valoarea argumentului. 

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țiunea 3 - Modificarea sau suprimarea validării suplimentare utilizând o variabilă de mediu

Aplicabilitate: Această opțiune se aplică doar pentru toate versiunile de .NET Framework.  Nu se aplică pentru .NET 6.0+.

Deși .NET Framework în mod implicit operațiunile de import limită pentru a nu avea mai mult de 600.000 de iterații ale unei parole, această limită poate fi configurată la nivel de aplicație sau la nivel de computer utilizând o variabilă de mediu. Această nouă limită se va aplica tuturor invocațiilor API afectate listate mai sus.

Pentru a modifica limita, setați variabila de mediuCOMPlus_Pkcs12UnspecifiedPasswordIterationLimitla valoarea limitei noi. De exemplu, pentru a seta limita la 1.000.000 (un milion) de iterații, setați variabila de mediu așa cum se arată mai jos.

  • Acest număr controlează limita totală de iterație, care este suma numărului de iterații MAC, a conținutului criptat și a numărului de iterații al sacoșei giulgiate. Dacă ați exportat manual un PFX utilizând un număr de iterații explicit <iter_count> (de exemplu, prin intermediul openssl pkcs12 -export -iter <iter_count>) și doriți să importați acel blob PFX, setați această variabilă de mediu la o valoare cel puțin la fel de mare ca suma tuturor iterațiilor așteptate. În practică, .NET Framework și .NET pot permite ca numărul total de iterații să depășească ușor orice limită explicită configurată aici.

COMPlus_Pkcs12UnspecifiedPasswordIterationLimit=1000000

Pentru a suprima complet verificările suplimentare, setați variabila de mediu la valoarea specială sentinel -1, așa cum se arată mai jos.

  • ⚠️ Avertisment: setați valoarea variabilei de mediu la -1 doar dacă sunteți sigur că aplicația țintă nu gestionează intrări de certificate care nu sunt de încredere.

COMPlus_Pkcs12UnspecifiedPasswordIterationLimit=-1

Opțiunea 4 - Modificarea sau suprimarea validării suplimentare utilizând AppContext

Aplicabilitate: Această opțiune se aplică doar pentru .NET 6.0+.  Nu se aplică pentru .NET Framework

Deși .NET limitează implicit operațiunile de import pentru a nu avea mai mult de 600.000 de iterații ale unei parole, această limită poate fi configurată la nivel de aplicație utilizând comutatorul AppContext. Această nouă limită se va aplica tuturor invocațiilor API afectate listate mai sus.

Pentru a modifica limita, setați comutatorul AppContext System.Security.Cryptography.Pkcs12UnspecifiedPasswordIterationLimit la valoarea limitei noi. De exemplu, pentru a seta limita la 1.000.000 (un milion) de iterații, setați comutatorul așa cum se arată mai jos.

  • Acest număr controlează limita totală de iterație, care este suma numărului de iterații MAC, a conținutului criptat și a numărului de iterații al sacoșei giulgiate. Dacă ați exportat manual un PFX utilizând un număr de iterații explicit <iter_count> (de exemplu, prin intermediul openssl pkcs12 -export -iter <iter_count>) și doriți să importați acel blob PFX, setați această variabilă de mediu la o valoare cel puțin la fel de mare ca suma tuturor iterațiilor așteptate. În practică, .NET poate permite ca numărul total de iterații să depășească ușor orice limită explicită configurată aici.

Pentru a seta comutarea în fișierul proiect al aplicației (.csproj sau .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>

Alternativ, puteți plasa un fișier denumit runtimeconfig.template.json cu următorul conținut în același director care conține fișierul de proiect al aplicației:

{

     "configProperties": {

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

      }

}

Pentru mai multe informații despre modificarea setărilor de configurare pentru runtime .NET, consultați pagina de documentație .NET Runtime configuration settings.

Pentru a suprima complet verificările suplimentare, setați comutatorul de configurare valoarea specială sentinel -1, așa cum se arată mai jos.

⚠️ Avertisment: setați comutatorul AppContext la -1 doar dacă sunteți sigur că aplicația țintă nu gestionează intrări de certificate care nu sunt de încredere.

În fișierul de proiect al aplicației (.csproj sau .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>

Sau în fișierul runtimeconfig.template.json:

{

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

     }

}

Opțiunea 5 - Modificarea sau suprimarea dispozitivului de validare suplimentar prin registry (numai în Windows pentru .NET Framework)

Aplicabilitate: Această opțiune se aplică doar pentru toate versiunile de .NET Framework.  Nu se aplică pentru .NET 6.0+.

Deși .NET Framework în mod implicit ca operațiunile de import-limită să nu depășească 600.000 de iterații ale unei parole, această limită poate fi configurată la nivel de mașină utilizând registry-ul HKLM. Această nouă limită se va aplica tuturor invocațiilor API afectate listate mai sus.

Pentru a modifica limita, sub cheia de registryHKLM\Software\Microsoft\.NETFramework, setați valoareaPkcs12UnspecifiedPasswordIterationLimitla noua limită. De exemplu, pentru a seta limita la 1.000.000 (un milion) de iterații, rulați comenzile așa cum se arată mai jos dintr-o linie de comandă cu drepturi sporite.

  • Acest număr controlează limita totală de iterație, care este suma numărului de iterații MAC, a conținutului criptat și a numărului de iterații al sacoșei giulgiate. Dacă ați exportat manual un PFX utilizând un număr de iterații explicit <iter_count> (de exemplu, prin openssl pkcs12 -export -iter <iter_count>) și doriți să importați acel blob PFX, setați această valoare de registry la o valoare cel puțin la fel de mare ca suma tuturor iterațiilor așteptate. În practică, .NET Framework poate permite ca numărul total de iterații să depășească ușor orice limită explicită configurată aici.

  • Setarea de registry depinde de arhitectură. Pentru a vă asigura că aplicațiile respectă valoarea configurată, indiferent de arhitectura lor țintă, nu uitați să modificați atât registrele pe 32 de biți, cât și pe cele pe 64 de biți, așa cum se arată mai jos.

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

Pentru a suprima complet verificările suplimentare, setați valoarea de registry la -1 dintr-o linie de comandă cu drepturi sporite, așa cum se arată mai jos.

  • ⚠️ Avertisment: setați valoarea de registry la -1 doar dacă sunteți sigur că serviciile care rulează pe computerul țintă nu gestionează intrări de certificate care nu sunt de încredere.

  • Pentru a seta santinela -1, utilizați tipul de REG_SZ în locul tipului de REG_DWORD. Setarea de registry depinde de arhitectură. Pentru a vă asigura că aplicațiile respectă valoarea configurată, indiferent de arhitectura lor țintă, nu uitați să modificați atât registrele pe 32 de biți, cât și pe cele pe 64 de biți, așa cum se arată mai jos.

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

Pentru a anula modificările din registry, ștergeți valoarea reg Pkcs12UnspecifiedPasswordIterationLimit dintr-o linie de comandă cu drepturi sporite.

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

Note specifice Windows

În Windows, .NET Framework importați certificate prin funcția PFXImportCertStore. Această funcție efectuează propria validare, incluzând plasarea propriilor limite pe numărul maxim permis de iterații al unui blob PFX. Aceste verificări vor avea loc în continuare la importul PFX. Butonul . Variabilele de mediu și cheile de registry specifice NET descrise mai sus nu afectează modul în care PFXImportCertStore efectuează aceste verificări.

Aveți nevoie de ajutor suplimentar?

Doriți mai multe opțiuni?

Explorați avantajele abonamentului, navigați prin cursurile de instruire, aflați cum să vă securizați dispozitivul și multe altele.

Comunitățile vă ajută să adresați întrebări și să răspundeți la întrebări, să oferiți feedback și să primiți feedback de la experți cu cunoștințe bogate.