Obs! Revidert 22. juni 2023 for å oppdatere oppløsning og midlertidige løsninger
Obs! Revidert 15. juni 2023 for å oppdatere løsningen rundt alternativ 4 og 5
Bakgrunn
13. juni 2023 lanserte Microsoft en sikkerhetsoppdatering for .NET Framework og .NET som påvirker hvordan kjøretiden importerer X.509-sertifikater. Disse endringene kan føre til at X.509-sertifikatimport genererer CryptographicException i scenarier der importen ville ha vært vellykket før oppdateringen.
Dette dokumentet beskriver endringene og midlertidige løsninger som er tilgjengelige for berørte programmer.
Berørt programvare
- .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
Berørte API-er
- new X509Certificate(byte[])
- X509Certificate.Import(byte[])
- new X509Certificate2(byte[])
- X509Certificate2.Import(byte[])
- X509Certificate2Collection.Import(byte[])
Beskrivelse av endring
Før endringen fra 13. juni 2023, når .NET Framework og .NET blir presentert med en binær sertifikatblob for import, vil .NET Framework og .NET vanligvis delegere validering og import av bloben til det underliggende operativsystemet. I Windows vil for eksempel .NET Framework og .NET vanligvis stole på API-et PFXImportCertStore for validering og import.
Fra og med endringen 13. juni 2023, når .NET Framework og .NET blir presentert med en binær sertifikatblob for import, vil .NET Framework og .NET i noen tilfeller utføre ytterligere validering før bloben leveres til det underliggende operativsystemet. Denne ekstra valideringen utfører en rekke heuristiske kontroller for å finne ut om det innkommende sertifikatet ville bruke opp ressurser ved import. Siden dette er ytterligere validering utover det det underliggende operativsystemet normalt ville utført, kan det blokkere sertifikatblober som ville blitt importert før endringen 13. juni 2023.
Kjente regresjoner
Hvis et X.509-sertifikat har blitt eksportert som en PFX-blob ved hjelp av et usedvanlig høyt antall passordgjentagelser, kan det hende at sertifikatet nå ikke kan importeres. De fleste tjenester for sertifikateksport bruker et iterasjonsantall et sted mellom 2 000 og 10 000. Når sikkerhetsoppdateringen er installert, mislykkes import for sertifikater som inneholder et iterasjonsantall som er større enn 600 000.
Hvis et X.509-sertifikat har blitt eksportert ved hjelp av et nullpassord [f.eks. via
X509Certificate.Export(X509ContentType.Pfx, (string)null)eller passordløstX509Certificate.Export(X509ContentType.Pfx)], kan det hende at sertifikatet nå ikke kan importeres.
Obs!
Regresjonen ovenfor har blitt håndtert i oppdateringen fra 22. juni 2023 som ble diskutert i KB5028608.
Hvis et X.509-sertifikat har blitt eksportert som en PFX-blob ved hjelp av Windows' funksjon for å beskytte den private nøkkelen til en SID, kan det hende at sertifikatet nå ikke kan importeres. Dette vil påvirke PFX-blober som opprettes på følgende måter:
- via Windows' veiviser for sertifikateksport og spesifiserer i veiviseren at den private nøkkelen skal beskyttes til en domenebruker; eller
- Via PowerShell-cmdleten Export-PfxCertificate der et eksplisitt
-ProtectToargument er angitt, eller - Via certutil-verktøyet der et eksplisitt
-protecttoargument oppgis; eller - Via API-et PFXExportCertStoreEx der PKCS12_PROTECT_TO_DOMAIN_SIDS flagget er angitt.
Løsning & midlertidige løsninger
Det finnes ulike løsninger, avhengig av om du vil gjøre målrettede endringer på individuelle kallenettsteder i koden, eller du vil endre virkemåten til ett enkelt program, eller du vil gjøre endringer på tvers av hele maskinen.
Alternativ 1 (foretrukket) – installer en oppdatert oppdatering
Obs!
Dette er det foretrukne alternativet fordi det adresserer ofte rapporterte kunderegresjoner og ikke krever kodeendringer for programmet.
Anvendelighet: Dette alternativet gjelder for alle versjoner av .NET Framework og .NET.
Dette problemet er løst i oppdateringen fra 22. juni 2023 som ble diskutert i KB5028608.
Microsoft anbefaler at kunder som opplever regresjoner introdusert av utgivelsen 13. juni 2023, prøver å installere denne oppdaterte oppdateringen før de prøver løsningene som er oppført senere i dette dokumentet.
Alternativ 2 – Endre samtalenettstedet
Anvendelighet: Dette alternativet gjelder for alle versjoner av .NET Framework og .NET.
Vurder om bloben du importerer, er pålitelig. Ble for eksempel bloben hentet fra en klarert plassering, for eksempel en database eller konfigurasjonsfil under din kontroll, eller ble den levert via en nettverksforespørsel fra en klient som ikke var godkjent eller ikke privilegert?
Microsoft anbefaler på det sterkeste at du ikke importerer PFX-blober fra klienter som ikke er godkjente eller ikke-privilegerte, siden disse blobene kan inneholde atferd ved ondsinnet ressurstømming.
Hvis du må importere en sertifikatblob for fellesnøkkel som du har fått fra en ikke-klarert part, kan du bruke følgende kode til å importere en slik blob på en sikker måte. Denne eksempelkoden bruker GetCertContentType-metoden til å finne ut hva den underliggende typen sertifikatblob er, og den avviser PFX-blober i tilfeller der du bare forventer å importere en sertifikatblob med fellesnøkkel. Konstruktøren X509Certificate2(byte[]) er trygg å bruke når den gis ikke-klarerte ikke-PFX-blober.
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);
}
}
Hvis du trenger å importere en sertifikatblob uten passordløs nøkkel og du har fastslått at bloben er pålitelig, kan du undertrykke de ekstra valideringskontrollene som utføres av sikkerhetsutgivelsen fra 13. juni 2023, ved å kalle en annen konstruktøroverbelastning. Du kan for eksempel kalle konstruktøren overload som godtar et strengpassordargument og sender null for argumentverdien.
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);
Alternativ 3 – Endre eller undertrykke tilleggsvalideringen ved hjelp av en miljøvariabel
Anvendelighet: Dette alternativet gjelder bare for alle versjoner av .NET Framework. Den gjelder ikke for .NET 6.0+.
Mens .NET Framework som standard begrenser importoperasjoner til ikke å utføre mer enn 600 000 gjentakelser av et passord, kan denne grensen konfigureres for hele appen eller hele maskinen ved hjelp av en miljøvariabel. Denne nye grensen vil gjelde for alle aktiveringer av de berørte API-ene som er oppført ovenfor.
Hvis du vil endre grensen, setter du miljøvariabelen COMPlus_Pkcs12UnspecifiedPasswordIterationLimit til verdien for hva den nye grensen skal være. Hvis du for eksempel vil angi en grense på 1 000 000 (én million) gjentakelser, angir du miljøvariabelen som vist nedenfor.
- Dette tallet styrer den totale iterasjonsgrensen, som er summen av antall MAC-gjentagelser, kryptert klarert innhold og gjentakelsesantall for skjult pose. Hvis du har eksportert en PFX manuelt ved hjelp av en eksplisitt iter_count> for antall <gjentakelser (for eksempel via openssl pkcs12 -export -iter <iter_count>) og ønsker å importere denne PFX-bloben, setter du denne miljøvariabelen til en verdi som er minst like stor som summen av alle forventede gjentakelser. I praksis kan .NET Framework og .NET tillate at det totale antallet iterasjoner overskrider en eksplisitt grense som er konfigurert her.
COMPlus_Pkcs12UnspecifiedPasswordIterationLimit=1000000
Hvis du vil hindre de ekstra kontrollene fullstendig, setter du miljøvariabelen til den spesielle sentinelverdien -1, som vist nedenfor.
- ⚠️ Advarsel: Sett bare miljøvariabelverdien til -1 hvis du er sikker på at målprogrammet ikke håndterer uklarerte sertifikatinndata.
COMPlus_Pkcs12UnspecifiedPasswordIterationLimit=-1
Alternativ 4 – Endre eller undertrykke tilleggsvalideringen ved hjelp av AppContext
Anvendelighet: Dette alternativet gjelder kun for .NET 6.0+. Den gjelder ikke for .NET Framework
Mens .NET som standard begrenser importoperasjoner til ikke å utføre mer enn 600 000 gjentakelser av et passord, kan denne grensen konfigureres for hele programmet ved hjelp av AppContext-bryteren. Denne nye grensen vil gjelde for alle aktiveringer av de berørte API-ene som er oppført ovenfor.
Hvis du vil endre grensen, setter du AppContext-bryteren System.Security.Cryptography.Pkcs12UnspecifiedPasswordIterationLimit til verdien for hva den nye grensen skal være. Hvis du for eksempel vil angi en grense til 1 000 000 (én million) gjentakelser, stiller du bryteren som vist nedenfor.
- Dette tallet styrer den totale iterasjonsgrensen, som er summen av antall MAC-gjentagelser, kryptert klarert innhold og gjentakelsesantall for skjult pose. Hvis du har eksportert en PFX manuelt ved hjelp av en eksplisitt iter_count> for antall <gjentakelser (for eksempel via openssl pkcs12 -export -iter <iter_count>) og ønsker å importere denne PFX-bloben, setter du denne miljøvariabelen til en verdi som er minst like stor som summen av alle forventede gjentakelser. I praksis kan .NET tillate at det totale antallet iterasjoner overskrider en eksplisitt grense som konfigureres her.
Slik stiller du inn bryteren i programmets prosjektfil (.csproj eller .vbproj):
<!--
- Denne bryteren fungerer bare hvis den gjeldende prosjektfilen representerer et program. Det har ingen virkning hvis gjeldende prosjektfil representerer et delt bibliotek.
-->
<ItemGroup>
- <RuntimeHostConfigurationOption include="System.Security.Cryptography.Pkcs12UnspecifiedPasswordIterationLimit" Value="1000000" />
</ItemGroup>
Du kan også plassere en fil kalt runtimeconfig.template.json med følgende innhold i samme mappe som inneholder programmets prosjektfil:
{
"configProperties": {
- System.Security.Cryptography.Pkcs12UnspecifiedPasswordIterationLimit: 1000000
}
}
Hvis du vil ha mer informasjon om hvordan du endrer konfigurasjonsinnstillinger for .NET-kjøretid, kan du se dokumentasjonssiden Konfigurasjonsinnstillinger for .NET-kjøretid.
For å undertrykke de ekstra kontrollene helt, still konfigurasjonsbryteren inn den spesielle sentinelverdien -1, som vist nedenfor.
⚠️ Advarsel: Sett AppContext-bryteren til -1 bare hvis du er sikker på at målprogrammet ikke håndterer uklarerte sertifikatinndata.
I programmets prosjektfil (.csproj eller .vbproj):
<!--
- Denne bryteren fungerer bare hvis den gjeldende prosjektfilen representerer et program. Det har ingen virkning hvis gjeldende prosjektfil representerer et delt bibliotek.
-->
<ItemGroup>
- <RuntimeHostConfigurationOption include="System.Security.Cryptography.Pkcs12UnspecifiedPasswordIterationLimit" Value="-1" />
</ItemGroup>
Eller i den runtimeconfig.template.json filen:
{
- "configProperties": {
- System.Security.Cryptography.Pkcs12UnspecifiedPasswordIterationLimit: -1
}
}
Alternativ 5 – endre eller undertrykke tilleggsvalideringen på hele maskinen via registret (bare for Windows for .NET Framework)
Anvendelighet: Dette alternativet gjelder bare for alle versjoner av .NET Framework. Den gjelder ikke for .NET 6.0+.
Mens .NET Framework som standard begrenser importoperasjoner til ikke å utføre mer enn 600 000 gjentakelser av et passord, kan denne grensen konfigureres for hele maskinen ved hjelp av HKLM-registeret. Denne nye grensen vil gjelde for alle aktiveringer av de berørte API-ene som er oppført ovenfor.
Hvis du vil endre grensen, angir du verdien Pkcs12UnspecifiedPasswordIterationLimit til den nye grensen under registernøkkelenHKLM\Software\Microsoft\.NETFramework. Hvis du for eksempel vil angi grensen til 1 000 000 (én million) gjentakelser, kjører du kommandoene som vist nedenfor fra en hevet ledetekst.
- Dette tallet styrer den totale iterasjonsgrensen, som er summen av antall MAC-gjentagelser, kryptert klarert innhold og gjentakelsesantall for skjult pose. Hvis du har eksportert en PFX manuelt ved hjelp av et eksplisitt iterasjonsantall <iter_count> (f.eks. via openssl pkcs12 -export -iter <iter_count>) og ønsker å importere denne PFX-bloben, angir du denne registerverdien til en verdi som er minst like stor som summen av alle forventede gjentakelser. I praksis kan .NET Framework tillate at det totale antallet iterasjoner overskrider en eksplisitt grense som er konfigurert her.
- Registerinnstillingen avhenger av arkitektur. Hvis du vil sikre at programmer observerer den konfigurerte verdien uavhengig av målarkitekturen, må du huske å endre både 32- og 64-bitersregistrene, som vist nedenfor.
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
Hvis du vil undertrykke de ekstra kontrollene fullstendig, angir du registerverdien til -1 fra en hevet ledetekst, som vist nedenfor.
- ⚠️ Advarsel! Bare angi registerverdien til -1 hvis du er sikker på at tjenestene som kjører på målmaskinen, ikke håndterer ikke-klarerte sertifikatinndata.
- For å angi -1 sentinel bruker du REG_SZ type i stedet for REG_DWORD type. Registerinnstillingen avhenger av arkitektur. Hvis du vil sikre at programmer observerer den konfigurerte verdien uavhengig av målarkitekturen, må du huske å endre både 32- og 64-bitersregistrene, som vist nedenfor.
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
Hvis du vil tilbakestille registerendringene, sletter du registerregisterverdien Pkcs12UnspecifiedPasswordIterationLimit fra en hevet ledetekst.
reg delete "HKLM\Software\Microsoft\.NETFramework" /v Pkcs12UnspecifiedPasswordIterationLimit /reg:32
reg delete "HKLM\Software\Microsoft\.NETFramework" /v Pkcs12UnspecifiedPasswordIterationLimit /reg:64
Windows-spesifikke notater
I Windows importerer .NET Framework sertifikater via PFXImportCertStore-funksjonen. Denne funksjonen utfører sin egen validering, inkludert å sette sine egne grenser for et maksimalt tillatte iterasjonsantall for en PFX-blob. Disse kontrollene vil fortsatt finne sted ved PFX-import. På . NET-spesifikke miljøvariabler og registernøkler som er beskrevet ovenfor, påvirker ikke hvordan PFXImportCertStore utfører disse kontrollene.