Pastaba: Peržiūrėta 2023 m. birželio 22 d., kad būtų atnaujinta rezoliucija ir sprendimo būdai
Pastaba: Peržiūrėta 2023 m. birželio 15 d., siekiant atnaujinti 4 ir 5 parinkčių veikimą
Pagrindiniai faktai
2023 m. birželio 13 d. "„Microsoft“" išleido ".NET Framework" ir ".NET" saugos naujinimą, kuris turi įtakos vykdyklės X.509 sertifikatų importavimui. Dėl šių pakeitimų importuojant X.509 sertifikatą gali kilti "CryptographicException" scenarijuose, kuriuose importavimas būtų pavykęs prieš atnaujinimą.
Šiame dokumente aprašomi pakeitimai ir galimi sprendimo būdai paveiktose programose.
Paveikta programinė įranga
- .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
Paveiktos API
- new X509Certificate(byte[])
- X509Certificate.Import(baitas[])
- new X509Certificate2(byte[])
- X509Certificate2.Import(baitas[])
- X509Certificate2Collection.Import(byte[])
Pakeitimo aprašas
Iki 2023 m. birželio 13 d. pakeitimo, kai ".NET Framework" ir ".NET" pateikiamas dvejetainis sertifikato didelis dvejetainis objektas, ".NET Framework" ir ".NET" paprastai perduodavo didelio dvejetainio objekto tikrinimą ir importavimą pagrindinei OS. Pvz., sistemoje "Windows" ".NET Framework" ir ".NET" paprastai tikrinant ir importuojant naudoja PFXImportCertStore API.
Nuo 2023 m. birželio 13 d. pakeitimo, kai ".NET Framework" ir ".NET" importavimui pateikiamas dvejetainis sertifikato didelis dvejetainis objektas, ".NET Framework" ir ".NET" tam tikromis aplinkybėmis atliks papildomą tikrinimą prieš perduodami dvejetainį objektą pagrindinei OS. Šis papildomas tikrinimas atlieka euristinius patikrinimus, kad nustatytų, ar importuojant gaunamas sertifikatas piktybiškai išeikvotų išteklius. Kadangi tai papildomas tikrinimas , viršijantis įprastus esamos OS tikrinimus, jis gali užblokuoti sertifikatų dvejetainius objektus, kurie būtų sėkmingai importuoti prieš 2023 m. birželio 13 d. pakeitimą.
Žinomos regresijos
Jei X.509 sertifikatas buvo eksportuotas kaip PFX didelis dvejetainis objektas naudojant neįprastai didelį slaptažodžių iteracijų skaičių, to sertifikato gali nepavykti importuoti. Dauguma sertifikatų eksportavimo priemonių naudoja iteracijų skaičių nuo 2 000 iki 10 000. Pritaikius saugos naujinimą, importuoti nepavyks sertifikatų, kuriuose yra iteracijų skaičius, didesnis nei 600 000.
Jei X.509 sertifikatas buvo eksportuotas naudojant nulinį slaptažodį [pvz., per arba be
X509Certificate.Export(X509ContentType.Pfx, (string)null)X509Certificate.Export(X509ContentType.Pfx)]slaptažodžio, to sertifikato dabar gali nepavykti importuoti.
Pastaba
Pirmiau pateikta regresija išspręsta 2023 m. birželio 22 d. naujinime, aptartame KB5028608.
Jei X.509 sertifikatas buvo eksportuotas kaip PFX didelis objektas, naudojant "Windows" galimybę apsaugoti privatųjį raktą SID, to sertifikato gali nepavykti importuoti. Tai turės įtakos PFX dvejetainiams objektams, sukurtiems tokiu būdu:
- Per "Windows" sertifikatų eksportavimo vediklį ir vedlyje nurodant, kad privatus raktas turi būti apsaugotas domeno vartotojui; arba
- Naudojant "PowerShell" " Export-PfxCertificate " cmdlet, kai pateikiamas aiškus
-ProtectToargumentas, arba - Per " Certutil " programą, kai pateikiamas aiškus
-protecttoargumentas; arba - Per PFXExportCertStoreEx API, kur pateikiama PKCS12_PROTECT_TO_DOMAIN_SIDS žymė.
Sprendimo & būdai
Galimi įvairūs sprendimo būdai, atsižvelgiant į tai, ar norite atlikti tikslinius keitimus atskirose skambučių svetainėse naudodami kodą, ar norite keisti vienos programos veikimą, ar norite atlikti keitimus visame kompiuteryje.
1 būdas (pageidaujama) – įdiekite atnaujintą pataisą
Pastaba
Tai yra pageidaujama parinktis, nes ji skirta dažniausiai pranešamoms klientų regresijoms ir nereikalauja jokių kodo pakeitimų programoje.
Taikymas: Ši parinktis taikoma visoms ".NET Framework" ir ".NET" versijoms.
Ši problema išspręsta 2023 m. birželio 22 d. naujinime, aptartame KB5028608.
"„Microsoft“" rekomenduoja klientams, kurie susiduria su regresijomis, įdiegtomis iki 2023 m. birželio 13 d. leidimo, pabandyti įdiegti šią atnaujintą pataisą prieš bandant toliau šiame dokumente nurodytus sprendimo būdus.
2 parinktis – skambučio svetainės modifikavimas
Taikymas: Ši parinktis taikoma visoms ".NET Framework" ir ".NET" versijoms.
Apsvarstykite, ar importuojamas didelis objektas yra patikimas. Pvz., ar dvejetainis objektas buvo gautas iš patikimos vietos, pvz., duomenų bazės arba konfigūracijos failo, kurį valdote jūs, ar jis buvo pateiktas per tinklo užklausą, kurią pateikė neautentifikuotas arba neprivilegijuotas klientas?
"„Microsoft“" primygtinai rekomenduoja neimportuoti PFX dvejetainių objektų, kuriuos jums pateikė neautentifikuoti arba neprivilegijuoti klientai, nes šiuose dvejetainiuose objektuose gali būti kenkėjiškų išteklių išeikvojimo veiksmų.
Jei turite importuoti viešojo rakto sertifikato dvejetainį objektą, kurį jums suteikė nepatikima šalis, galite naudoti toliau nurodytą kodą, kad saugiai importuotumėte tokį dvejetainį objektą. Šis kodo pavyzdys naudoja metodą "GetCertContentType ", kad nustatytų, koks yra pagrindinis sertifikato didelio dvejetainio objekto tipas, ir atmeta PFX dvejetainius objektus tais atvejais, kai planuojate importuoti tik viešojo rakto sertifikato dvejetainį objektą. Konstruktorius X509Certificate2(byte[]) yra saugus naudoti, kai suteikiami nepatikimi ne PFX blobs.
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);
}
}
Jei turite importuoti beslaptažodžio privataus rakto sertifikato dvejetainį objektą ir nustatėte, kad dvejetainis objektas yra patikimas, galite neleisti papildomų tikrinimo patikrų, atliktų iki 2023 m. birželio 13 d. saugos leidimo, iškviesdami kitą konstruktoriaus perkrovą. Pvz., galite iškviesti konstruktoriaus perkrovą, kuri priima eilutės slaptažodžio argumentą ir kaip argumento reikšmę perduoda nulį.
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 parinktis. Papildomo tikrinimo modifikavimas arba sustabdymas naudojant aplinkos kintamąjį
Taikymas: Ši parinktis taikoma tik visoms ".NET Framework" versijoms. Jis netaikomas .NET 6.0+.
Nors pagal numatytuosius nustatymus ".NET Framework" importavimo operacijas riboja ne daugiau nei 600 000 slaptažodžio iteracijų, šis apribojimas gali būti sukonfigūruotas visos programos arba kompiuterio mastu naudojant aplinkos kintamąjį. Šis naujas apribojimas bus taikomas visiems pirmiau išvardytų paveiktų API iškvietimams.
Norėdami pakeisti ribą, nustatykite aplinkos kintamąjį COMPlus_Pkcs12UnspecifiedPasswordIterationLimit į tokią, kokia turėtų būti nauja riba. Pavyzdžiui, norėdami nustatyti 1 000 000 (vieno milijono) iteracijų ribą, nustatykite aplinkos kintamąjį, kaip parodyta toliau.
- Šis skaičius valdo bendrą iteracijos limitą, kuris yra MAC iteracijų skaičiaus, užšifruoto saugaus turinio ir gaubto maišelio iteracijų skaičiaus suma. Jei rankiniu būdu eksportavote PFX naudodami tiesioginį iteracijų skaičių <iter_count> (pvz., per openssl pkcs12 -export -iter <iter_count>) ir norite importuoti tą PFX dvejetainį objektą, nustatykite šio aplinkos kintamojo reikšmę, kuri būtų bent tokia pat didelė kaip visų numatomų iteracijų suma. Praktiškai ".NET Framework" ir ".NET" gali leisti bendram iteracijų skaičiui šiek tiek viršyti bet kokią čia sukonfigūruotą ribą.
COMPlus_Pkcs12UnspecifiedPasswordIterationLimit=1000000
Norėdami visiškai panaikinti papildomas patikras, nustatykite aplinkos kintamąjį į specialią kontrolinę reikšmę -1, kaip parodyta toliau.
- ⚠️ Įspėjimas: aplinkos kintamojo reikšmę nustatykite į -1 tik tuo atveju, jei esate tikri, kad tikslinė programa neapdoroja nepatikimo sertifikato įvesties.
COMPlus_Pkcs12UnspecifiedPasswordIterationLimit=-1
4 parinktis. Papildomo tikrinimo modifikavimas arba sustabdymas naudojant "AppContext"
Taikymas: ši parinktis taikoma tik .NET 6.0+. Jis netaikomas ".NET Framework"
Nors pagal numatytuosius nustatymus .NET importavimo operacijas riboja ne daugiau nei 600 000 slaptažodžio iteracijų, šis apribojimas gali būti sukonfigūruotas visoje programoje naudojant "AppContext" jungiklį. Šis naujas apribojimas bus taikomas visiems pirmiau išvardytų paveiktų API iškvietimams.
Norėdami pakeisti ribą, nustatykite AppContext jungiklį System.Security.Cryptography.Pkcs12Unspecified PasswordIterationLimit į naują limito reikšmę. Pavyzdžiui, norėdami nustatyti 1 000 000 (vienas milijonas) iteracijų ribą, nustatykite jungiklį, kaip parodyta toliau.
- Šis skaičius valdo bendrą iteracijos limitą, kuris yra MAC iteracijų skaičiaus, užšifruoto saugaus turinio ir gaubto maišelio iteracijų skaičiaus suma. Jei rankiniu būdu eksportavote PFX naudodami tiesioginį iteracijų skaičių <iter_count> (pvz., per openssl pkcs12 -export -iter <iter_count>) ir norite importuoti tą PFX dvejetainį objektą, nustatykite šio aplinkos kintamojo reikšmę, kuri būtų bent tokia pat didelė kaip visų numatomų iteracijų suma. Praktiškai .NET gali leisti bendram iteracijų skaičiui šiek tiek viršyti bet kokią čia sukonfigūruotą ribą.
Norėdami nustatyti jungiklį programos projekto faile (.csproj arba .vbproj):
<!--
- Šis raktas veikia tik tuo atveju, jei dabartinis projekto failas atitinka programą. Neturi įtakos, jei dabartinis projekto failas yra bendrinama biblioteka.
-->
<ItemGroup>
- <RuntimeHostConfigurationOption include="System.Security.Cryptography.Pkcs12Unspecified PasswordIterationLimit" value="1000000" />
</ItemGroup>
Arba galite įdėti failą pavadinimu runtimeconfig.template.json su tokiu turiniu tame pačiame kataloge, kuriame yra jūsų programos projekto failas:
{
"configProperties": {
- "System.Security.Cryptography.Pkcs12Unspecified PasswordIterationLimit": 1000000
}
}
Daugiau informacijos apie .NET vykdyklės konfigūracijos parametrų keitimą žr. dokumentacijos puslapyje .NET vykdyklės konfigūracijos parametrai.
Norėdami visiškai sustabdyti papildomas patikras, nustatykite konfigūracijos jungiklį į specialiąją sargybinę reikšmę -1, kaip parodyta toliau.
⚠️ Įspėjimas: nustatykite "AppContext" jungiklį į -1 tik tuo atveju, jei esate tikri, kad tikslinė programa neapdoroja nepatikimo sertifikato įvesties.
Paraiškos projekto byloje (.csproj arba .vbproj):
<!--
- Šis raktas veikia tik tuo atveju, jei dabartinis projekto failas atitinka programą. Neturi įtakos, jei dabartinis projekto failas yra bendrinama biblioteka.
-->
<ItemGroup>
- <RuntimeHostConfigurationOption include="System.Security.Cryptography.Pkcs12Unspecified PasswordIterationLimit" value="-1" />
</ItemGroup>
Arba runtimeconfig.template.json faile:
{
- "configProperties": {
- "System.Security.Cryptography.Pkcs12Unspecified PasswordIterationLimit": -1
}
}
5 parinktis. Papildomo tikrinimo įrenginio modifikavimas arba sustabdymas visame registre (tik "Windows" ".NET Framework")
Taikymas: Ši parinktis taikoma tik visoms ".NET Framework" versijoms. Jis netaikomas .NET 6.0+.
Nors pagal numatytuosius nustatymus ".NET Framework" importavimo operacijas riboja ne daugiau nei 600 000 slaptažodžio iteracijų, šis limitas gali būti sukonfigūruotas visoje mašinoje naudojant HKLM registrą. Šis naujas apribojimas bus taikomas visiems pirmiau išvardytų paveiktų API iškvietimams.
Norėdami pakeisti ribą, registro rakte HKLM\Software\„Microsoft“\.NETFrameworknustatykite reikšmę Pkcs12UnspecifiedPasswordIterationLimit , kokia turėtų būti nauja riba. Pvz., norėdami nustatyti 1 000 000 (vienas milijonas) iteracijų ribą, vykdykite toliau parodytas komandas iš didesnių teisių komandinės eilutės.
- Šis skaičius valdo bendrą iteracijos limitą, kuris yra MAC iteracijų skaičiaus, užšifruoto saugaus turinio ir gaubto maišelio iteracijų skaičiaus suma. Jei rankiniu būdu eksportavote PFX naudodami iteracijų skaičių <iter_count> (pvz., per openssl pkcs12 -export -iter <iter_count>) ir norite importuoti tą PFX dvejetainį objektą, nustatykite šios registro reikšmės reikšmę, kuri būtų bent tokia pat didelė kaip visų numatomų iteracijų suma. Praktiškai ".NET Framework" gali leisti bendram iteracijų skaičiui šiek tiek viršyti bet kokią čia sukonfigūruotą ribą.
- Registro parametrai priklauso nuo architektūros. Norėdami užtikrinti, kad programos laikytųsi sukonfigūruotos reikšmės nepaisant jų tikslinės architektūros, nepamirškite modifikuoti ir 32, ir 64 bitų registrų, kaip parodyta toliau.
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
Norėdami visiškai neįtraukti papildomų tikrinimų, didesnių teisių komandinėje eilutėje nustatykite registro reikšmę į -1, kaip parodyta toliau.
- ⚠️ Įspėjimas: nustatykite registro reikšmę į -1 tik tuo atveju, jei esate tikri, kad tiksliniame kompiuteryje veikiančios paslaugos neapdoroja nepatikimo sertifikato įvesties.
- Norėdami nustatyti -1 sargybinę, naudokite REG_SZ tipą, o ne REG_DWORD tipą. Registro parametrai priklauso nuo architektūros. Norėdami užtikrinti, kad programos laikytųsi sukonfigūruotos reikšmės nepaisant jų tikslinės architektūros, nepamirškite modifikuoti ir 32, ir 64 bitų registrų, kaip parodyta toliau.
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
Norėdami atšaukti registro pakeitimus, panaikinkite Pkcs12UnspecifiedPasswordIterationLimit registro reikšmę iš didesnių teisių komandinės eilutės.
reg delete "HKLM\Software\Microsoft\.NETFramework" /v Pkcs12UnspecifiedPasswordIterationLimit /reg:32
reg delete "HKLM\Software\Microsoft\.NETFramework" /v Pkcs12UnspecifiedPasswordIterationLimit /reg:64
"Windows" būdingos pastabos
Sistemoje "Windows" ".NET Framework" importuoja sertifikatus naudodama funkciją PFXImportCertStore. Ši funkcija atlieka savo tikrinimą, įskaitant savo ribų pateikimą didžiausiam leidžiamam PFX dvejetainio objekto iteracijų skaičiui. Šie patikrinimai vis tiek bus atliekami importuojant PFX. . Anksčiau aprašyti tinklo aplinkos kintamieji ir registro raktai neturi įtakos tam, kaip PFXImportCertStore atlieka šias patikras.