Uwaga: Poprawiono 22 czerwca 2023 r., aby zaktualizować rozwiązanie i obejścia
Uwaga: Poprawiono 15 czerwca 2023 r. w celu zaktualizowania obejścia opcji 4 i 5
Tle
13 czerwca 2023 r. firma Microsoft wydała aktualizację zabezpieczeń dla programów .NET Framework i .NET, która wpływa na sposób importowania certyfikatów X.509 w czasie wykonywania. Te zmiany mogą spowodować, że import certyfikatu X.509 zwróci cryptographicException w scenariuszach, w których importowanie zakończyło się pomyślnie przed aktualizacją.
W tym dokumencie opisano zmiany i obejścia dostępne dla aplikacji, których dotyczy problem.
Oprogramowanie, którego dotyczy problem
-
.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
Interfejsy API, których dotyczy problem
Opis zmiany
Przed 13 czerwca 2023 r., zmiana, gdy .NET Framework i .NET jest przedstawiony z obiektem blob certyfikatu binarnego do importu, .NET Framework i .NET zazwyczaj delegowania weryfikacji i importu obiektu blob do systemu operacyjnego źródłowego. Na przykład w systemie Windows .NET Framework i .NET zwykle korzystają z interfejsu API PFXImportCertStore do sprawdzania poprawności i importowania.
Począwszy od 13 czerwca 2023 r., zmiana, gdy .NET Framework i .NET jest prezentowany z obiektem blob certyfikatu binarnego do importu, .NET Framework i .NET w pewnych okolicznościach wykonać dodatkowe sprawdzanie poprawności przed przekazaniem obiektu blob do źródłowego systemu operacyjnego. Ta dodatkowa weryfikacja wykonuje serię heurystycznych testów w celu ustalenia, czy certyfikat przychodzący złośliwie wyczerpuje zasoby podczas importowania. Ponieważ jest to dodatkowa weryfikacja wykraczającą poza to, co podstawowy system operacyjny normalnie wykonuje, może zablokować obiekty blob certyfikatu, które zostałyby pomyślnie zaimportowane przed zmianą z 13 czerwca 2023 r.
Znane regresje
-
Jeśli certyfikat X.509 został wyeksportowany jako obiekt blob PFX z niezbyt dużą liczbą iteracji haseł, ten certyfikat może się teraz nie udać. Większość obiektów eksportu certyfikatów korzysta z liczby iteracji gdzieś między 2000 - 10 000. Po zastosowaniu aktualizacji zabezpieczeń importowanie kończy się niepowodzeniem dla certyfikatów zawierających liczbę iteracji większą niż 600 000.
-
Jeśli certyfikat X.509 został wyeksportowany przy użyciu hasła null [np. za pośrednictwemX509Certificate.Export(X509ContentType.Pfx, (string)null)lubX509Certificate.Export(X509ContentType.Pfx)]bez hasła, ten certyfikat może się teraz nie udać.
Uwaga: Powyższa regresja została rozwiązana w aktualizacji z 22 czerwca 2023 r., omówionym w aktualizacji KB5028608.
-
Jeśli certyfikat X.509 został wyeksportowany jako obiekt blob PFX przy użyciu funkcji systemu Windows do ochrony klucza prywatnego na identyfikatorze SID, ten certyfikat może się teraz nie udać. Będzie to miało wpływ na obiekty blob PFX utworzone w następujący sposób:
-
Za pomocą Kreatora eksportu certyfikatów systemu Windows i określając w kreatorze, że klucz prywatny powinien być chroniony dla użytkownika domeny; Lub
-
Za pośrednictwem polecenia cmdlet Export-PfxCertificate programu PowerShell, w którym podano jawny argument -ProtectTo ; Lub
-
Za pośrednictwem narzędzia certutil , w którym podano wyraźny argument -protectto ; Lub
-
Za pośrednictwem interfejsu API PFXExportCertStoreEx , w którym jest podana flaga PKCS12_PROTECT_TO_DOMAIN_SIDS.
-
Rozwiązywanie & obejściach
Istnieją różne obejścia w zależności od tego, czy chcesz wprowadzić zmiany kierowane w poszczególnych witrynach połączeń w ramach kodu, czy chcesz zmienić zachowanie pojedynczej aplikacji, czy chcesz wprowadzić zmiany na całym komputerze.
Opcja 1 (preferowana) — zainstaluj zaktualizowaną poprawkę
Uwaga: Jest to preferowana opcja, ponieważ rozwiązuje ona często zgłaszane regresje klientów i nie wymaga żadnych zmian kodu w aplikacji.
Zastosowanie: Ta opcja ma zastosowanie do wszystkich wersji programów .NET Framework i .NET.
Ten problem został rozwiązany w aktualizacji z 22 czerwca 2023 r., omówionym w aktualizacji KB5028608.
Firma Microsoft zaleca klientom, u których występują regresje wprowadzone 13 czerwca 2023 r., przed podjęciem próby obejścia wymienionych w dalszej części tego dokumentu, spróbuj zainstalować tę zaktualizowaną poprawkę.
Opcja 2 . Modyfikowanie witryny połączenia
Zastosowanie: Ta opcja ma zastosowanie do wszystkich wersji programów .NET Framework i .NET.
Zastanów się, czy importowane obiekty blob są godne zaufania. Czy na przykład obiekt blob został pobrany z zaufanej lokalizacji, takiej jak baza danych lub plik konfiguracji, pod Twoją kontrolą, czy też został dostarczony za pośrednictwem żądania sieciowego złożonego przez klienta nieuwierzytelnionego lub nieuwierzytelnionego?
Firma Microsoft zdecydowanie zaleca, aby nie importować obiektów blob PFX dostarczonych przez klientów nieuwierzytelnionych lub nieuwierzytelnionych, ponieważ te obiekty blob mogą zawierać złośliwe zachowania związane z wyczerpaniem zasobów.
Jeśli chcesz zaimportować obiekt blob certyfikatu klucza publicznego przekazany Ci przez niezaufaną stronę, możesz użyć następującego kodu, aby bezpiecznie zaimportować taki obiekt blob. Ten przykładowy kod używa metody GetCertContentType w celu określenia typu obiektu blob certyfikatu i odrzuca obiekty blob PFX w przypadkach, gdy oczekuje się tylko zaimportować obiekt blob certyfikatu klucza publicznego. KonstruktorX509Certificate2(byte[]) jest bezpieczny w użyciu w przypadku niezaufanych obiektów blob innych niż 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);
}
}
Jeśli chcesz zaimportować obiekt blob certyfikatu klucza prywatnego bez hasła i wiesz, że obiekt blob jest godny zaufania, możesz pominąć dodatkowe testy poprawności wykonywane w wydaniu zabezpieczeń z 13 czerwca 2023 r., wywołując inne przeciążenie konstruktora. Można na przykład wywołać przeciążenie konstruktora, które akceptuje argument hasło ciągu i przekazać wartość null dla wartości argumentu.
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);
Opcja 3. Modyfikowanie lub pomijanie dodatkowego sprawdzania poprawności przy użyciu zmiennej środowiskowej
Zastosowanie: Ta opcja dotyczy tylko wszystkich wersji .NET Framework. Nie dotyczy programu .NET 6.0+.
Podczas gdy .NET Framework domyślnie ograniczyć operacje importowania do wykonywania nie więcej niż 600 000 iteracji hasła, limit ten można skonfigurować w całej aplikacji lub na całym komputerze przy użyciu zmiennej środowiskowej. Ten nowy limit będzie miał zastosowanie do wszystkich wywołań interfejsów API, na które ma to wpływ wymienione powyżej.
Aby zmienić limit, ustaw zmienną środowiskowąCOMPlus_Pkcs12UnspecifiedPasswordIterationLimitwartość nowego limitu. Aby na przykład ustawić limit na 1000 000 (milion) iteracji, ustaw zmienną środowiskową, jak pokazano poniżej.
-
Ta liczba steruje całkowitym limitem iteracji, czyli sumą liczby iteracji mac, zaszyfrowanej bezpiecznej zawartości i liczby iteracji całunowanej torby. Jeśli ręcznie wyeksportowano format PFX przy użyciu jawnej liczby iteracji <iter_count> (np. poprzez otwarcie pliku pkcs12 -export -iter <iter_count>) i chcesz zaimportować ten obiekt blob PFX, ustaw tę zmienną środowiskową na wartość co najmniej tak dużą jak suma wszystkich oczekiwanych iteracji. W praktyce .NET Framework i .NET mogą zezwolić na nieznaczne przekroczenie całkowitego limitu iteracji.
COMPlus_Pkcs12UnspecifiedPasswordIterationLimit=1000000
Aby całkowicie pominąć dodatkowe testy, ustaw zmienną środowiskową na specjalną wartość wskaźnikową -1, jak pokazano poniżej.
-
⚠️ Ostrzeżenie: Ustaw wartość zmiennej środowiskowej na -1 tylko wtedy, gdy masz pewność, że aplikacja docelowa nie obsługuje niezaufanych danych wejściowych certyfikatu.
COMPlus_Pkcs12UnspecifiedPasswordIterationLimit=-1
Opcja 4. Modyfikowanie lub pomijanie dodatkowego sprawdzania poprawności przy użyciu funkcji AppContext
Zastosowanie: Ta opcja dotyczy tylko programu .NET 6.0+. Nie dotyczy .NET Framework
Program .NET domyślnie ogranicza operacje importowania do nie więcej niż 600 000 iteracji hasła, ale ten limit można skonfigurować dla całej aplikacji przy użyciu przełącznika AppContext. Ten nowy limit będzie miał zastosowanie do wszystkich wywołań interfejsów API, na które ma to wpływ wymienione powyżej.
Aby zmienić limit, ustaw przełącznik AppContext System.Security.Cryptography.Pkcs12UnspecifiedPasswordIterationLimit na wartość nowego limitu. Aby na przykład ustawić limit na 1000 000 (milion) iteracji, ustaw przełącznik tak, jak pokazano poniżej.
-
Ta liczba steruje całkowitym limitem iteracji, czyli sumą liczby iteracji mac, zaszyfrowanej bezpiecznej zawartości i liczby iteracji całunowanej torby. Jeśli ręcznie wyeksportowano format PFX przy użyciu jawnej liczby iteracji <iter_count> (np. poprzez otwarcie pliku pkcs12 -export -iter <iter_count>) i chcesz zaimportować ten obiekt blob PFX, ustaw tę zmienną środowiskową na wartość co najmniej tak dużą jak suma wszystkich oczekiwanych iteracji. W praktyce program .NET może zezwolić na nieznaczne przekroczenie całkowitego limitu iteracji.
Aby ustawić przełącznik w pliku projektu aplikacji (csproj lub 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>
Możesz również umieścić plik o nazwie runtimeconfig.template.json z następującą zawartością w tym samym katalogu, który zawiera plik projektu aplikacji:
{
"configProperties": {
- "System.Security.Cryptography.Pkcs12UnspecifiedPasswordIterationLimit": 1000000
}
}
Aby uzyskać więcej informacji na temat zmieniania ustawień konfiguracji środowiska uruchomieniowego .NET, zobacz stronę dokumentacji ustawień konfiguracji środowiska uruchomieniowego .NET.
Aby całkowicie pominąć dodatkowe testy, ustaw przełącznik konfiguracji specjalną wartość wskaźnikową -1, jak pokazano poniżej.
⚠️ Ostrzeżenie: Ustaw przełącznik AppContext na -1 tylko wtedy, gdy masz pewność, że aplikacja docelowa nie obsługuje niezaufanych danych wejściowych certyfikatu.
W pliku projektu aplikacji (csproj lub 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>
Lub w pliku runtimeconfig.template.json:
{
- "configProperties": {
- "System.Security.Cryptography.Pkcs12UnspecifiedPasswordIterationLimit": -1
}
}
Opcja 5 . Modyfikowanie lub pomijanie dodatkowego komputera sprawdzania poprawności za pośrednictwem rejestru (tylko system Windows dla .NET Framework)
Zastosowanie: Ta opcja dotyczy tylko wszystkich wersji .NET Framework. Nie dotyczy programu .NET 6.0+.
Podczas gdy .NET Framework domyślnie ograniczyć operacje importowania do wykonywania nie więcej niż 600 000 iteracji hasła, limit ten można skonfigurować na całym komputerze przy użyciu rejestru HKLM. Ten nowy limit będzie miał zastosowanie do wszystkich wywołań interfejsów API, na które ma to wpływ wymienione powyżej.
Aby zmienić limit, w kluczu rejestruHKLM\Software\Microsoft\.NETFrameworkustaw wartośćPkcs12UnspecifiedPasswordIterationLimitna nowy limit. Aby na przykład ustawić limit na 1000 000 (milion) iteracji, uruchom polecenia, jak pokazano poniżej w wierszu polecenia z podwyższonym poziomem uprawnień.
-
Ta liczba steruje całkowitym limitem iteracji, czyli sumą liczby iteracji mac, zaszyfrowanej bezpiecznej zawartości i liczby iteracji całunowanej torby. Jeśli ręcznie wyeksportowano rekord PFX przy użyciu jawnej liczby iteracji <iter_count> (np. poprzez otwarcie pliku pkcs12 -export -iter <iter_count>) i chcesz zaimportować ten obiekt blob PFX, ustaw tę wartość rejestru na wartość co najmniej tak dużą, jak suma wszystkich oczekiwanych iteracji. W praktyce .NET Framework może zezwolić na nieznaczne przekroczenie całkowitego limitu iteracji.
-
Ustawienie rejestru jest zależne od architektury. Aby upewnić się, że aplikacje obserwują skonfigurowaną wartość niezależnie od architektury docelowej, należy zmodyfikować zarówno rejestry 32-bitowe, jak i 64-bitowe, jak pokazano poniżej.
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
Aby całkowicie pominąć dodatkowe testy, ustaw wartość rejestru na -1 z wiersza polecenia z podwyższonym poziomem uprawnień, jak pokazano poniżej.
-
⚠️ Ostrzeżenie: Ustaw wartość rejestru na -1 tylko wtedy, gdy masz pewność, że usługi uruchomione na komputerze docelowym nie obsługują niezaufanych danych wejściowych certyfikatu.
-
Aby ustawić wskaźnik -1, użyj typu REG_SZ zamiast typu REG_DWORD. Ustawienie rejestru jest zależne od architektury. Aby upewnić się, że aplikacje obserwują skonfigurowaną wartość niezależnie od architektury docelowej, należy zmodyfikować zarówno rejestry 32-bitowe, jak i 64-bitowe, jak pokazano poniżej.
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
Aby przywrócić zmiany rejestru, usuń wartość reg Pkcs12UnspecifiedPasswordIterationLimit z wiersza polecenia z podwyższonym poziomem uprawnień.
reg delete "HKLM\Software\Microsoft\.NETFramework" /v Pkcs12UnspecifiedPasswordIterationLimit /reg:32 reg delete "HKLM\Software\Microsoft\.NETFramework" /v Pkcs12UnspecifiedPasswordIterationLimit /reg:64
Notatki specyficzne dla systemu Windows
W systemie Windows .NET Framework zaimportować certyfikaty za pomocą funkcji PFXImportCertStore. Ta funkcja wykonuje własne sprawdzanie poprawności, łącznie z wprowadzeniem własnych limitów dla maksymalnej dopuszczalnej liczby iteracji obiektu blob PFX. Kontrole te będą nadal przeprowadzane po imporcie PFX. Tthe. Opisane powyżej zmienne środowiskowe i klucze rejestru specyficzne dla sieci nie mają wpływu na sposób wykonywania tych testów przez PFXImportCertStore.