Beleške: Revidirano 22. juna 2023. za ažuriranje rezolucije i privremenih rešenja
Beleške: Korigoovano 15. juna 2023. za ažuriranje rada sa opcijama 4 i 5
Pozadini
13. juna 2023. Microsoft je objavio bezbednosnu ispravku za .NET Framework i .NET koja utiče na način izvršavanja uvoza X.509 certifikata. Ove promene mogu dovesti do toga da uvoz X.509 certifikata baci CryptographicException u scenarije u kojima bi uvoz uspeo pre ažuriranja.
Ovaj dokument opisuje promene i privremena rešenja dostupna za aplikacije na koje ovo utiče.
Softver na koji ovo utiče
-
.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
Ugroženi API-ji
Opis promene
Pre 13. juna 2023. godine, promena kada se .NET Framework i .NET predstave sa blob binarnim certifikatom za uvoz, .NET Framework i .NET bi obično delegirati validaciju i uvoz bloba u osnovni OS. Na primer, u operativnim sistemima Windows, .NET Framework i .NET obično se oslanjaju na PFXImportCertStore API za proveru valjanosti i uvoz.
Od 13. juna 2023. godine, promena kada se .NET Framework i .NET predstave sa blob binarnim certifikatom za uvoz, .NET Framework i .NET će u nekim okolnostima izvršiti dodatnu proveru valjanosti pre nego što preda blob osnovnom operativnom sistemu. Ova dodatna provera valjanosti izvršava niz heurističkih provera kako bi se utvrdilo da li će dolazni certifikat zlonamerni iscrpljivati resurse pri uvozu. Pošto je ovo dodatna provera valjanosti izvan onoga što bi osnovni OS normalno izvršavao, on može da blokira blob certifikate koji bi se uspešno uvezli pre 13. juna 2023. godine.
Poznate regresije
-
Ako je X.509 certifikat izvezen kao PFX blob pomoću izuzetno visokog broja iteracije lozinke, taj certifikat možda neće uspeti da se uveze. Većina objekata za izvoz certifikata koristi iteraciju negde između 2000 i 10.000. Kada se primeni bezbednosna ispravka, uvoz neće uspeti za certifikate koji sadrže broj iteracije veći od 600.000.
-
Ako je X.509 certifikat izvezen pomoću lozinke bez vrednosti [npr. putem uslugeX509Certificate.Export(X509ContentType.Pfx, (string)null)ili lozinkeX509Certificate.Export(X509ContentType.Pfx)], taj certifikat možda neće uspeti da se uveze.
Napomena: Gorenavedena regresija rešena je u ispravci od 22. juna 2023. godine, koja je razmatrana u KB5028608.
-
Ako je X.509 certifikat izvezen kao PFX blob pomoću mogućnosti operativnog sistema Windows da zaštiti privatni ključ od SID-a, taj certifikat možda neće uspeti da se uveze. To će uticati na PFX blobove kreirane na sledeće načine:
-
Putem Windows čarobnjaka za izvoz certifikata i u čarobnjaku navode da privatni ključ treba da bude zaštićen od korisnika domena; Ili
-
Putem PowerShell datoteke Export-PfxCertificate cmdlet komande gde je obezbeđen izričit -ProtectTo argument; Ili
-
Putem certutil uslužnog programa gde je naveden eksplicitan -protectto argument; Ili
-
Putem PFXExportCertStoreEx API-ja gde je PKCS12_PROTECT_TO_DOMAIN_SIDS navedena zastavica.
-
Rešenja & zaobilazna rešenja
Postoje različita zaobilazna rešenja, u zavisnosti od toga da li želite da izvršite ciljane promene na pojedinačnim lokacijama poziva u okviru koda ili želite da promenite ponašanje jedne aplikacije ili želite da izvršite promene na računaru.
Opcija 1 (željena) – Instaliranje ažurirane zakrpi
Napomena: Ovo je željena opcija jer se ona odnosi na uobičajeno prijavljene regresije klijenata i ne zahteva promene koda aplikacije.
Primenjivost: Ova opcija se odnosi na sve verzije usluga .NET Framework i .NET.
Ovaj problem je rešen u ispravci od 22. juna 2023. opisane u KB5028608.
Microsoft preporučuje da klijenti koji imaju regresije, predstavljene 13. juna 2023, pokušaju da instaliraju ovu ažuriranu zakrpi pre nego što pokušate da privremeno rešite problem navedena kasnije u ovom dokumentu.
2. opcija – Izmena lokacije poziva
Primenjivost: Ova opcija se odnosi na sve verzije usluga .NET Framework i .NET.
Razmislite da li je blob koji uvozite pouzdan. Na primer, da li je blob preuzet sa pouzdane lokacije, kao što je baza podataka ili konfiguraciona datoteka pod vašom kontrolom ili je obezbeđen putem mrežnog zahteva koji je dao neovlašćeni ili neovlašćeni klijent?
Microsoft preporučuje da ne uvozite PFX blob datoteke koje su vam obezbedili neovlašćeni ili neprivileženi klijenti, jer ovi blobovi mogu da sadrže zlonamerna ponašanja iscrpnog resursa.
Ako treba da uvezete blob certifikata javnog ključa koji vam je dala nepouzdana strana, možete da koristite sledeći kôd da biste bezbedno uvezli takav blob. Ovaj uzorak koda koristi metod GetCertContentType da bi utvrdio koji je osnovni tip bloba certifikata i odbija PFX blob u slučajevima kada očekujete da uvezete samo blob certifikata javnog ključa. KonstruktorX509Certificate2(byte[]) je bezbedan za upotrebu kada su data nepouzdana BLOB polja koja nisu PFX.
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 treba da uvezete blob certifikata privatnog ključa bez lozinke i utvrdili ste da je blob pouzdan, možete da sprečite dodatne provere valjanosti koje su izvršene do 13. juna 2023. godine, bezbednosno izdanje pozivanjem drugog konstruktora preopterećenja. Na primer, možete da pozovete konstruktora koji prihvata argument lozinke niske i prosleđuje nulu za vrednost argumenta.
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);
Opcija 3 – Izmena ili sprečavanje dodatne provere valjanosti pomoću promenljive okruženja
Primenjivost: Ova opcija se odnosi samo na sve .NET Framework verzije. Ne odnosi se na .NET 6.0+.
Iako .NET Framework operacije uvoza podrazumevano ograničile da ne zahtevaju više od 600.000 iteracija lozinke, ovo ograničenje se može konfigurisati na nivou cele aplikacije ili na mašini pomoću promenljive okruženja. Ovo novo ograničenje primeniće se na sva pozivanja Ugroženih API-ja navedenih iznad.
Da biste promenili ograničenje, postavite promenljivuCOMPlus_Pkcs12UnspecifiedPasswordIterationLimitokruženja na vrednost koja bi trebalo da bude novo ograničenje. Na primer, da biste ograničenje postavili na 1.000.000 (milion) iteracija, postavite promenljivu okruženja kao što je prikazano ispod.
-
Ovaj broj kontroliše ukupno ograničenje iteracije , što predstavlja zbir mac broja iteracije, šifrovanog bezbednog sadržaja i broj iteracije u kesi. Ako ste ručno izvezli PFX pomoću eksplicitnog broja iteracija <iter_count> (npr. putem openssl pkcs12 -export -iter <iter_count>) i želite da uvezete taj PFX blob, postavite ovu promenljivu okruženja na vrednost koja ima najmanje jednu vrednost kao zbir svih očekivanih iteracija. U praksi, .NET Framework i .NET mogu da dozvole da ukupan broj iteracije neznatno premaši svako eksplicitno ograničenje konfigurisano ovde.
COMPlus_Pkcs12UnspecifiedPasswordIterationLimit=1000000
Da biste potpuno sprečili dodatne provere, podesite promenljivu okruženja na specijalnu sentinel vrednost -1, kao što je prikazano ispod.
-
⚠️ Upozorenje: postavite vrednost promenljive okruženja na -1 ako ste sigurni da ciljna aplikacija ne rukuje unosom nepouzdanog certifikata.
COMPlus_Pkcs12UnspecifiedPasswordIterationLimit=-1
Opcija 4 – Izmena ili sprečavanje dodatne provere valjanosti pomoću funkcije AppContext
Primena: Ova opcija se odnosi samo na .NET 6.0+. Ne odnosi se na .NET Framework
Iako .NET operacije uvoza podrazumevano ograničavanje ne zahtevaju više od 600.000 iteracija lozinke, ovo ograničenje se može konfigurisati na nivou aplikacije pomoću prekidača AppContext. Ovo novo ograničenje primeniće se na sva pozivanja Ugroženih API-ja navedenih iznad.
Da biste promenili ograničenje, postavite parametar AppContext da promeni System.Security.Cryptography.Pkcs12UnspecifiedPasswordIterationLimit na vrednost koja bi trebalo da bude novo ograničenje. Na primer, da biste ograničenje postavili na 1.000.000 (milion) iteracija, postavite prekidač kao što je prikazano ispod.
-
Ovaj broj kontroliše ukupno ograničenje iteracije, što predstavlja zbir mac broja iteracije, šifrovanog bezbednog sadržaja i broj iteracije u kesi. Ako ste ručno izvezli PFX pomoću eksplicitnog broja iteracija <iter_count> (npr. putem openssl pkcs12 -export -iter <iter_count>) i želite da uvezete taj PFX blob, postavite ovu promenljivu okruženja na vrednost koja ima najmanje jednu vrednost kao zbir svih očekivanih iteracija. U praksi, .NET može da dozvoli da ukupan broj iteracije neznatno premaši svako eksplicitno ograničenje konfigurisano ovde.
Da biste postavili prekidač u okviru 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="1000000" />
</ItemGroup>
Druga mogućnost je da datoteku pod imenom runtimeconfig.template.json postavite sa sledećim sadržajem u isti direktorijum koji sadrži datoteku projekta aplikacije:
{
"configProperties": {
- "System.Security.Cryptography.Pkcs12UnspecifiedPasswordIterationLimit": 1000000
}
}
Više informacija o promeni postavki konfiguracije .NET runtime-a potražite na stranici dokumentacije .NET Runtime postavki konfiguracije.
Da biste potpuno sprečili dodatne provere, podesite prekidač konfiguracije za prebacivanje specijalne sentinel vrednosti -1, kao što je prikazano ispod.
⚠️ Upozorenje: postavite prekidač AppContext na -1 ako ste sigurni da ciljna aplikacija ne rukuje unosom nepouzdanog certifikata.
U okviru 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 okviru datoteke runtimeconfig.template.json:
{
- "configProperties": {
- "System.Security.Cryptography.Pkcs12UnspecifiedPasswordIterationLimit": -1
}
}
5. opcija – Menjanje ili sprečavanje dodatne provere valjanosti mašine putem registratora (samo za Windows za .NET Framework)
Primenjivost: Ova opcija se odnosi samo na sve .NET Framework verzije. Ne odnosi se na .NET 6.0+.
Iako .NET Framework operacije uvoza ograničenja podrazumevano ne zahtevaju više od 600.000 iteracija lozinke, ovo ograničenje se može konfigurisati na nivou računara pomoću HKLM registratora. Ovo novo ograničenje primeniće se na sva pozivanja Ugroženih API-ja navedenih iznad.
Da biste promenili ograničenje, u okviru ključaHKLM\Software\Microsoft\.NETFrameworkregistratora postavite vrednostPkcs12UnspecifiedPasswordIterationLimitna ono što bi novo ograničenje trebalo da bude. Na primer, da biste ograničenje postavili na 1.000.000 (milion) iteracija, pokrenite komande kao što je prikazano ispod iz komandne linije sa punim privilegijama.
-
Ovaj broj kontroliše ukupno ograničenje iteracije , što predstavlja zbir mac broja iteracije, šifrovanog bezbednog sadržaja i broj iteracije u kesi. Ako ste ručno izvezli PFX pomoću eksplicitnog broja iteracije <iter_count> (npr. putem openssl pkcs12 -export -iter <iter_count>) i želite da uvezete taj PFX blob, postavite vrednost registratora na vrednost koja je najmanje velika kao zbir svih očekivanih iteracija. U praksi, .NET Framework da omogući da ukupan broj iteracije neznatno premaši bilo koje eksplicitno ograničenje konfigurisano ovde.
-
Postavka registratora zavisi od arhitekture. Da biste se uverili da aplikacije posmatraju vašu konfigurisanu vrednost bez obzira na njihovu ciljnu arhitekturu, ne zaboravite da izmenite i 32-bitne i 64-bitne registratore, kao što je prikazano ispod.
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 potpuno sprečili dodatne provere, postavite vrednost registratora na -1 sa komandne linije sa punim privilegijama, kao što je prikazano ispod.
-
⚠️ Upozorenje: vrednost registratora postavite samo na -1 ako ste sigurni da usluge pokrenute na ciljnom računaru ne rukuju unosom nepouzdanog certifikata.
-
Da biste podesili -1 sentinel, koristite tip REG_SZ tip "REG_DWORD". Postavka registratora zavisi od arhitekture. Da biste se uverili da aplikacije posmatraju vašu konfigurisanu vrednost bez obzira na njihovu ciljnu arhitekturu, ne zaboravite da izmenite i 32-bitne i 64-bitne registratore, kao što je prikazano ispod.
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 promene registratora, izbrišite vrednost reg-a Pkcs12UnspecifiedPasswordIterationLimit iz komandne linije sa punim privilegijama.
reg delete "HKLM\Software\Microsoft\.NETFramework" /v Pkcs12UnspecifiedPasswordIterationLimit /reg:32 reg delete "HKLM\Software\Microsoft\.NETFramework" /v Pkcs12UnspecifiedPasswordIterationLimit /reg:64
Beleške specifične za Windows
U operativnom sistemu Windows .NET Framework uvoz certifikata putem funkcije PFXImportCertStore. Ova funkcija izvršava sopstvenu proveru valjanosti, uključujući postavljanje sopstvenih ograničenja na maksimalan dozvoljeni broj iteracija PFX bloba. Ove provere će se i dalje izvršiti nakon uvoza PFX-a. .. Promenljive okruženja specifične za NET i ključeve registratora opisane iznad ne utiču na način na koji PFXImportCertStore izvršava ove provere.