Napomena: Revidirano 22. lipnja 2023. radi ažuriranja rješenja i zaobilaznih rješenja
Napomena: Revidirano 15. lipnja 2023. radi ažuriranja zaobilaznih mogućnosti 4. i 5.
Pozadini
13. lipnja 2023. Microsoft je objavio sigurnosno ažuriranje za .NET Framework i .NET koje utječe na način na koji izvođenje uvozi certifikate X.509. Te promjene mogu uzrokovati da uvoz certifikata X.509 baci CryptographicException u scenarijima u kojima bi uvoz bio uspješan prije ažuriranja.
U ovom se dokumentu opisuju promjene i zaobilazna rješenja dostupna za pogođene aplikacije.
Zahvaćeni softver
-
.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
Zahvaćeni API-ji
Opis promjene
Prije 13. lipnja 2023., promjena, kada su .NET Framework i .NET predstavljeni binarnim blobom certifikata za uvoz, .NET Framework i .NET obično bi delegirati provjeru valjanosti i uvoz bloba u temeljni OPERACIJSKI SUSTAV. Na primjer, u sustavu Windows, .NET Framework i .NET obično bi se oslanjali na API PFXImportCertStore za provjeru valjanosti i uvoz.
Od 13. lipnja 2023., promjena, kada se .NET Framework i .NET prikažu s binarnim blobom certifikata za uvoz, .NET Framework i .NET u nekim će okolnostima provesti dodatnu provjeru valjanosti prije nego što blob predate temeljnom OS-u. Ova dodatna provjera valjanosti izvodi niz heurističkih provjera da bi se utvrdilo bi li dolazni certifikat zlonamjerno iscrpljivao resurse nakon uvoza. Budući da je ovo dodatna provjera valjanosti nakon što bi operacijski sustav u pozadini normalno funkcionirao, može blokirati blobove certifikata koji bi se uspješno uvezli prije 13. lipnja 2023., promjene.
Poznate regresije
-
Ako je certifikat X.509 izvezen kao PFX blob s neuobičajeno visokim brojem iteracija lozinke, taj se certifikat sada možda neće moći uvesti. Većina izvoza certifikata koristi broj iteracija između 2000 i 10 000. Nakon primjene sigurnosnog ažuriranja uvoz neće uspjeti za certifikate koji sadrže broj iteracija veći od 600 000.
-
Ako je certifikat X.509 izvezen pomoću null lozinke [npr. putemX509Certificate.Export(X509ContentType.Pfx, (string)null)ili lozinke bezX509Certificate.Export(X509ContentType.Pfx)], taj se certifikat sada možda neće moći uvesti.
Napomena: Gore navedena regresija riješena je ažuriranjem od 22. lipnja 2023. o kojem je objašnjeno u ažuriranju KB5028608.
-
Ako je certifikat X.509 izvezen kao PFX blob pomoću mogućnosti sustava Windows za zaštitu privatnog ključa sid-a, taj se certifikat sada možda neće moći uvesti. To će utjecati na PFX blobove stvorene na sljedeći način:
-
Putem čarobnjaka za izvoz certifikata sustava Windows i u čarobnjaku navedite da privatni ključ treba biti zaštićen korisniku domene. Ili
-
Putem cmdleta Export-PfxCertificate komponente PowerShell u kojem -ProtectTo naveden eksplicitan argument; Ili
-
Putem uslužnog programa certutil u kojem -protectto naveden eksplicitan argument; Ili
-
Putem API-ja PFXExportCertStoreEx gdje je PKCS12_PROTECT_TO_DOMAIN_SIDS zastavica navedena.
-
Zaobilazna & rješenja
Postoje razna zaobilazna rješenja, ovisno o tome želite li unesite ciljane promjene na web-mjestima pojedinačnih poziva unutar koda ili želite promijeniti ponašanje jedne aplikacije ili želite unesite promjene na razini računala.
1. mogućnost (preferirana) – instalacija ažurirane zakrpe
Napomena: To je preferirana mogućnost jer se odnosi na najčešće prijavljene regresije korisnika i ne zahtijeva promjene koda u aplikaciji.
Primjenjivost: ta se mogućnost primjenjuje na sve verzije sustava .NET Framework i .NET.
Taj je problem riješen ažuriranjem od 22. lipnja 2023. o kojem je objašnjeno u ažuriranju KB5028608.
Microsoft preporučuje korisnicima koji nailaze na regresije uvedene 13. lipnja 2023., da pokušaju instalirati tu ažuriranu zakrpu prije nego što isprobaju zaobilazna rješenja navedena u nastavku ovog dokumenta.
2. mogućnost – izmjena web-mjesta poziva
Primjenjivost: ta se mogućnost primjenjuje na sve verzije sustava .NET Framework i .NET.
Razmislite je li blob koji uvozite pouzdan. Je li, primjerice, blob dohvaćen s pouzdanog mjesta, kao što je baza podataka ili konfiguracijska datoteka pod vašom kontrolom ili je poslan putem mrežnog zahtjeva koji je uputio neautorizirani klijent?
Microsoft vam svakako preporučuje da ne uvozite PFX blobove koje su vam dali neautorizirani ili neprivilegirani klijenti jer ti blobovi mogu sadržavati ponašanje iscrpljenosti zlonamjernog resursa.
Ako morate uvesti blob certifikata javnog ključa koji vam je dala nepouzdana strana, možete koristiti sljedeći kod da biste sigurno uvezli takav blob. Ovaj ogledni kod koristi metodu GetCertContentType za utvrđivanje temeljne vrste bloba certifikata i odbacuje PFX blobove u slučajevima kada očekujete uvoz bloba certifikata javnog ključa. KonstruktorX509Certificate2(byte[]) je siguran za korištenje kada se pridaju nepouzdani ne-PFX blobovi.
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);
}
}
Ako morate uvesti blob certifikata privatnog ključa bez lozinke i ustanovili ste da je blob pouzdan, možete potisnuti dodatne provjere valjanosti koje su obavili 13. lipnja 2023., sigurnosno izdanje pozivajući drugo preopterećenje graditelja. Možete, primjerice, nazvati preopterećenje graditelja koje prihvaća argument za lozinku niza i za vrijednost argumenta proslijedi null.
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);
3. mogućnost – izmjena ili obustava dodatne provjere valjanosti pomoću varijable okruženja
Primjenjivost: ta se mogućnost primjenjuje samo na sve .NET Framework verzije. Ne odnosi se na .NET 6.0+.
Premda .NET Framework prema zadanim postavkama, operacije uvoza ograničenja ne zauzimaju više od 600 000 iteracija lozinke, to se ograničenje može konfigurirati na razini aplikacije ili stroju pomoću varijable okruženja. Ovo će se novo ograničenje primijeniti na sve gore navedene api-je na koje se to odnosi.
Da biste promijenili ograničenje, postavite varijabluCOMPlus_Pkcs12UnspecifiedPasswordIterationLimitna vrijednost novog ograničenja. Da biste, primjerice, postavili ograničenje na 1000 000 (milijun) iteracija, postavite varijablu okruženja kao što je prikazano u nastavku.
-
Taj broj kontrolira ukupno ograničenje iteracije, što je zbroj broja iteracija MAC-a, šifriranog sigurnog sadržaja i broja iteracija u vreći s obavijesnim sadržajem. Ako ste RUČNO izvezli PFX pomoću eksplicitnog broja iteracija <iter_count> (npr. putem openssl pkcs12 -export -iter <iter_count>) i želite uvesti taj PFX blob, postavite varijablu okruženja na vrijednost barem kao zbroj svih očekivanih iteracija. U praksi .NET Framework i .NET mogu dopustiti da ukupni broj iteracija malo premaši eksplicitno ograničenje konfigurirano ovdje.
COMPlus_Pkcs12UnspecifiedPasswordIterationLimit=1000000
Da biste u potpunosti potisnuli dodatne provjere, postavite varijablu okruženja na posebnu sentinel vrijednost -1, kao što je prikazano u nastavku.
-
⚠️ Upozorenje: vrijednost varijable okruženja postavite na -1 samo ako ste sigurni da ciljna aplikacija ne rukuje nepouzdanim unosom certifikata.
COMPlus_Pkcs12UnspecifiedPasswordIterationLimit=-1
4. mogućnost – izmjena ili obustava dodatne provjere valjanosti pomoću aplikacije AppContext
Primjenjivost: ta se mogućnost odnosi samo na .NET 6.0+. Ne odnosi se na .NET Framework
Dok .NET prema zadanim postavkama ograničava operacije uvoza tako da ne zauzima više od 600 000 iteracija lozinke, to se ograničenje može konfigurirati na razini aplikacije pomoću prekidača AppContext. Ovo će se novo ograničenje primijeniti na sve gore navedene api-je na koje se to odnosi.
Da biste promijenili ograničenje, postavite parametar AppContext System.Security.Cryptography.Pkcs12UnspecifiedPasswordIterationLimit na vrijednost novog ograničenja. Da biste, primjerice, postavili ograničenje na 1000 000 (milijun) iteracija, postavite prekidač kao što je prikazano u nastavku.
-
Taj broj kontrolira ukupno ograničenje iteracije, što je zbroj broja iteracija MAC-a, šifriranog sigurnog sadržaja i broja iteracija u vreći s obavijesnim sadržajem. Ako ste RUČNO izvezli PFX pomoću eksplicitnog broja iteracija <iter_count> (npr. putem openssl pkcs12 -export -iter <iter_count>) i želite uvesti taj PFX blob, postavite varijablu okruženja na vrijednost barem kao zbroj svih očekivanih iteracija. U praksi .NET može dopustiti da ukupni broj iteracija malo premaši eksplicitno ograničenje konfigurirano ovdje.
Da biste postavili prekidač u datoteci projekta aplikacije (.csproj ili .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>
Umjesto toga, datoteku pod nazivom runtimeconfig.template.json možete s pomoću sljedećeg sadržaja postaviti u isti direktorij koji sadrži datoteku projekta vaše aplikacije:
{
"configProperties": {
- "System.Security.Cryptography.Pkcs12UnspecifiedPasswordIterationLimit": 1000000
}
}
Dodatne informacije o promjeni postavki konfiguracije izvođenja za .NET potražite na stranici dokumentacije .NET Runtime konfiguracijske postavke.
Da biste u potpunosti potisnuli dodatne provjere, postavite promjenu konfiguracije na posebnu vrijednost -1, kao što je prikazano u nastavku.
⚠️ Upozorenje: prekidač AppContext postavite na -1 samo ako ste sigurni da ciljna aplikacija ne rukuje nepouzdanim unosom certifikata.
Unutar datoteke projekta aplikacije (.csproj ili .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>
Ili u datoteci runtimeconfig.template.json:
{
- "configProperties": {
- "System.Security.Cryptography.Pkcs12UnspecifiedPasswordIterationLimit": -1
}
}
5. mogućnost – izmjena ili potiskivanje dodatne provjere valjanosti na razini računala putem registra (samo windows za .NET Framework)
Primjenjivost: ta se mogućnost primjenjuje samo na sve .NET Framework verzije. Ne odnosi se na .NET 6.0+.
Iako .NET Framework prema zadanim postavkama, operacije uvoza ograničenja ne mogu trajati više od 600 000 iteracija lozinke, to se ograničenje može konfigurirati na stroju pomoću HKLM registra. Ovo će se novo ograničenje primijeniti na sve gore navedene api-je na koje se to odnosi.
Da biste promijenili ograničenje, u odjeljku ključaHKLM\Software\Microsoft\.NETFrameworkpostavite vrijednostPkcs12UnspecifiedPasswordIterationLimitna novo ograničenje. Da biste, primjerice, postavili ograničenje na 1000 000 (milijun) iteracija, pokrenite naredbe kao što je prikazano u nastavku iz povišenog naredbenog retka.
-
Taj broj kontrolira ukupno ograničenje iteracije, što je zbroj broja iteracija MAC-a, šifriranog sigurnog sadržaja i broja iteracija u vreći s obavijesnim sadržajem. Ako ste RUČNO izvezli PFX pomoću eksplicitnog broja iteracija <iter_count> (npr. putem openssl pkcs12 -export -iter <iter_count>) i želite uvesti taj PFX blob, postavite tu vrijednost registra na vrijednost barem kao zbroj svih očekivanih iteracija. U praksi .NET Framework dopustiti da ukupni broj iteracija malo premaši eksplicitno ograničenje konfigurirano ovdje.
-
Postavka registra ovisi o arhitekturi. Da biste bili sigurni da aplikacije promatraju vašu konfiguriranu vrijednost bez obzira na njihovu ciljnu arhitekturu, ne zaboravite izmijeniti i 32-bitne i 64-bitne registre, kao što je prikazano u nastavku.
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
Da biste u potpunosti potisnuli dodatne provjere, postavite vrijednost registra na -1 iz povišenog naredbenog retka, kao što je prikazano u nastavku.
-
⚠️ Upozorenje: vrijednost registra postavite na -1 samo ako ste sigurni da servisi pokrenuti na ciljnom računalu ne rukuju nepouzdanim unosom certifikata.
-
Da biste postavili -1 sentinel, koristite REG_SZ umjesto REG_DWORD vrste. Postavka registra ovisi o arhitekturi. Da biste bili sigurni da aplikacije promatraju vašu konfiguriranu vrijednost bez obzira na njihovu ciljnu arhitekturu, ne zaboravite izmijeniti i 32-bitne i 64-bitne registre, kao što je prikazano u nastavku.
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
Da biste vratili promjene registra, izbrišite vrijednost registra Pkcs12UnspecifiedPasswordIterationLimit reg iz povišenog naredbenog retka.
reg delete "HKLM\Software\Microsoft\.NETFramework" /v Pkcs12UnspecifiedPasswordIterationLimit /reg:32 reg delete "HKLM\Software\Microsoft\.NETFramework" /v Pkcs12UnspecifiedPasswordIterationLimit /reg:64
Bilješke specifične za Windows
U sustavu Windows .NET Framework certifikate putem funkcije PFXImportCertStore. Ova funkcija provodi vlastitu provjeru valjanosti, uključujući postavljanje vlastitih ograničenja maksimalnog dopuštenog broja iteracija PFX bloba. Te će se provjere i dalje izvršavati nakon uvoza PFX-a. The . Gore opisane varijable okruženja i ključevi registra specifični za NET ne utječu na to kako PFXImportCertStore provodi te provjere.