Applies To.NET

Забележка: Променено на 22 юни 2023 г., за да актуализирате разделителната способност и заобиколните решения

Забележка: Преработено на 15 юни 2023 г., за да се актуализират опциите 4 и 5 за заобикаляне на заобиколните условия 

Фон

На 13 юни 2023 г. Microsoft издаде актуализация на защитата за .NET Framework (платформа) и .NET, която влияе върху начина, по който runtime импортира сертификати X.509. Тези промени може да доведат до това импортирането на X.509 сертификат да хвърли CryptographicException в сценарии, при които импортирането би било успешно преди актуализацията.

Този документ описва промените и заобиколните решения, налични за засегнатите приложения.

Засегнат софтуер

  • .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

Засегнати API

Описание на промяната

Преди 13 юни 2023 г. променете, когато .NET Framework (платформа) и .NET се представят с блоб на двоичен сертификат за импортиране, .NET Framework (платформа) и .NET обикновено делегират проверката и импортирането на blob в базовата операционна система. Например в Windows .NET Framework (платформа) и .NET обикновено разчитат на API на PFXImportCertStore за проверка и импортиране.

Считано от 13 юни 2023 г., променете, когато .NET Framework (платформа) и .NET са представени с двоичен blob сертификат за импортиране, .NET Framework (платформа) и .NET в някои случаи ще извършат допълнителна проверка, преди да предаде blob на базовата операционна система. Тази допълнителна проверка извършва поредица от евристични проверки, за да определи дали входящият сертификат злонамерено ще изчерпи ресурсите при импортиране. Тъй като това е допълнителна проверка извън нормалното изпълнение на базовата операционна система, тя може да блокира blob на сертификата, които биха били успешно импортирани преди 13 юни 2023 г., да се променят.

Известни регресии

  1. Ако X.509 сертификат е експортиран като PFX блоб с помощта на необичайно висок брой итерации на пароли, този сертификат може да не успее да импортира. Повечето съоръжения за експортиране на сертификати използват брой итерации някъде между 2000 и 10 000. След като се приложи актуализацията на защитата, импортирането ще е неуспешно за сертификати, съдържащи брой итерации, по-голям от 600 000.

  2. Ако сертификат X.509 е експортиран с парола Null [например чрезX509Certificate.Export(X509ContentType.Pfx, (string)null)или чрезX509Certificate.Export(X509ContentType.Pfx)]без парола, този сертификат може да не успее да се импортира.  

    Забележка: Горепосочената регресия е разгледана в актуализацията от 22 юни 2023 г., обсъдена в KB5028608.

  3. Ако сертификат X.509 е експортиран като PFX блоб с помощта на възможностите на Windows за защита на личния ключ на SID, този сертификат може да не успее да импортира. Това ще повлияе на PFX blobs, създадени по следните начини:

    • Чрез съветника за експортиране на сертификати на Windows и указване в съветника, че личният ключ трябва да бъде защитен за потребител на домейн; Или

    • Чрез кратката команда Export-PfxCertificate на PowerShell, където е предоставен явен аргумент за -ProtectTo ; Или

    • Чрез помощната програма certutil , където е предоставен явен -protectto аргумент; Или

    • Чрез PFXExportCertStoreEx API, където е предоставен флагът PKCS12_PROTECT_TO_DOMAIN_SIDS.

Разрешаване & заобиколни решения

Съществуват различни заобиколни решения в зависимост от това дали искате да направите целеви промени в отделни сайтове за повикване във вашия код, или искате да промените поведението на едно приложение, или искате да направите промени в цялата машина.

Опция 1 (предпочитана) – Инсталиране на актуализирана корекция

Забележка: Това е предпочитаната опция, тъй като обръща внимание на често съобщавани регресии на клиенти и не изисква промени в кода на приложението.

Приложимост: Тази опция се отнася за всички версии на .NET Framework (платформа) и .NET.

Този проблем е решен в актуализацията от 22 юни 2023 г., обсъдена в KB5028608.

Microsoft препоръчва на клиентите, които имат регресии, въведени от изданието от 13 юни 2023 г., да се опитат да инсталират тази актуализирана корекция, преди да се опитат заобиколните решения, изброени по-нататък в този документ.

Опция 2 – Промяна на сайта за повикване

Приложимост: Тази опция се отнася за всички версии на .NET Framework (платформа) и .NET.

Помислете дали блобът, който импортирате, е надежден. Например дали блобът е извлечен от надеждно местоположение, например база данни или конфигурационен файл под ваш контрол, или е предоставен чрез искане за мрежа, направено от неудостоверени или невилегирани клиенти?

Microsoft силно препоръчва да не импортирате PFX BLOB, предоставени ви от неудостоверени или непривилегировани клиенти, тъй като тези големи двоични обект може да съдържат злонамерено изчерпване на ресурси.

Ако трябва да импортирате голям длан на сертификат за публичен ключ, даден ви от ненадеждна страна, можете да използвате следния код, за да импортирате безопасно такъв голям длан. Този примерен код използва метода GetCertContentType, за да определи какъв е базовият тип на BLOB на сертификата и отхвърля PFX големи дразнения в случаите, когато очаквате да импортирате само блоб на сертификат за публичен ключ. Конструкторът наX509Certificate2(byte[]) е безопасен за използване, когато са дадени ненадеждни не-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);
    }
} 

Ако трябва да импортирате блоб на сертификат за личен ключ без парола и сте установили, че блобът е надежден, можете да забраните допълнителните проверки за проверка, извършени от 13 юни 2023 г., издание на защитата, като извикате претоварване на друг конструктор. Например можете да извикате конструктора да претовари, който приема аргумент с парола за низ, и да предаде 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 – Промяна или потискане на допълнителната проверка с помощта на променлива на средата

Приложимост: Тази опция се отнася само за всички версии на .NET Framework (платформа).  Тя не се отнася за .NET 6.0+.

Докато .NET Framework (платформа) по подразбиране операциите за импортиране на ограничението да отнемат не повече от 600 000 итерации на парола, това ограничение може да бъде конфигурирано на база за приложение или за цялата машина с помощта на променлива на средата. Това ново ограничение ще се приложи за всички извиквания на засегнатите API, изброени по-горе.

За да промените ограничението, задайте променливата на средатаCOMPlus_Pkcs12UnspecifiedPasswordIterationLimitна стойността на това, което трябва да бъде новото ограничение. Например за да зададете ограничението на 1 000 000 (един милион) итерации, задайте променливата за средата, както е показано по-долу.

  • Това число определя ограничението за общата итерация , което е сумата от броя на итерациите на MAC, шифрованото безопасно съдържание и броя итерации на торбичката с шрут. Ако сте експортирали ръчно PFX с помощта на явен брой итерации <iter_count> (например чрез openssl pkcs12 -export -iter <iter_count>) и искате да импортирате този PFX blob, задайте тази променлива на среда на стойност, която е поне толкова голяма, колкото сумата на всички очаквани итерации. На практика .NET Framework (платформа) и .NET могат да позволят общият брой итерации да превиши леко всяко изрично ограничение, конфигурирано тук.

COMPlus_Pkcs12UnspecifiedPasswordIterationLimit=1000000

За да потиснат напълно допълнителните проверки, задайте променливата на средата на специалната стойност на "страж" -1, както е показано по-долу.

  • ⚠️ Предупреждение: Задайте стойността на променливата на средата на -1 само ако сте сигурни, че целевото приложение не обработва въвеждане на ненадежден сертификат.

COMPlus_Pkcs12UnspecifiedPasswordIterationLimit=-1

Опция 4 – Промяна или потискане на допълнителната проверка с помощта на AppContext

Приложимост: Тази опция се отнася за .NET 6.0+only.  Той не се прилага за .NET Framework (платформа)

Докато операциите за импортиране на .NET по подразбиране отнемат не повече от 600 000 итерации на парола, това ограничение може да се конфигурира за целия приложение с помощта на ключа AppContext. Това ново ограничение ще се приложи за всички извиквания на засегнатите API, изброени по-горе.

За да промените ограничението, задайте превключвателя AppContext System.Security.Cryptography.Pkcs12UnspecifiedPasswordIterationLimit на стойността на това, което трябва да бъде новото ограничение. Например за да зададете ограничението на 1 000 000 (един милион) итерации, задайте превключвателя, както е показано по-долу.

  • Това число определя ограничението за общата итерация, което е сумата от броя на итерациите на MAC, шифрованото безопасно съдържание и броя итерации на торбичката с шрут. Ако сте експортирали ръчно PFX с помощта на явен брой итерации <iter_count> (например чрез openssl pkcs12 -export -iter <iter_count>) и искате да импортирате този PFX blob, задайте тази променлива на среда на стойност, която е поне толкова голяма, колкото сумата на всички очаквани итерации. На практика .NET може да позволи общият брой итерации да превиши леко всяко изрично конфигурирано ограничение тук.

За да зададете превключвателя във файла на проекта на вашето приложение (.csproj или .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>

Като алтернатива можете да поставите файл с име runtimeconfig.template.json със следното съдържание в същата директория, която съдържа файла на проекта на вашето приложение:

{

     "configProperties": {

  • "System.Security.Cryptography.Pkcs12UnspecifiedPasswordIterationLimit": 1000000

      }

}

За повече информация относно промяната на настройките за конфигуриране на изпълнимия модул на .NET вж. страницата с документация .NET Runtime конфигурационни настройки.

За да потиснете напълно допълнителните проверки, задайте ключа за конфигуриране на специалната стойност на "сентинел - 1", както е показано по-долу.

⚠️ Предупреждение: Задайте ключа AppContext на -1 само ако сте сигурни, че целевото приложение не обработва въвеждане на ненадежден сертификат.

Във файла на проекта на приложението (.csproj или .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>

Или във файла runtimeconfig.template.json:

{

  • "configProperties": { 
  •     "System.Security.Cryptography.Pkcs12UnspecifiedPasswordIterationLimit": -1

     }

}

Опция 5 – Промяна или забраняване на допълнителната проверка за цялата машина чрез системния регистър (само за Windows за .NET Framework (платформа))

Приложимост: Тази опция се отнася само за всички версии на .NET Framework (платформа).  Тя не се отнася за .NET 6.0+.

Докато .NET Framework (платформа) по подразбиране операциите за импортиране на ограничението да отнемат не повече от 600 000 итерации на парола, това ограничение може да бъде конфигурирано за цялата машина с помощта на HKLM системния регистър. Това ново ограничение ще се приложи за всички извиквания на засегнатите API, изброени по-горе.

За да промените ограничението, под ключа от системния регистърHKLM\Software\Microsoft\.NETFrameworkзадайте стойносттаPkcs12UnspecifiedPasswordIterationLimitна това, което трябва да бъде новото ограничение. Например за да зададете ограничението на 1 000 000 (един милион) итерации, изпълнете командите, както е показано по-долу от команден прозорец с администраторски права.

  • Това число определя ограничението за общата итерация , което е сумата от броя на итерациите на MAC, шифрованото безопасно съдържание и броя итерации на торбичката с шрут. Ако сте експортирали ръчно PFX с помощта на явен брой итерации, <iter_count> (например чрез openssl pkcs12 -export -iter <iter_count>) и искате да импортирате този PFX blob, задайте тази стойност на системния регистър на стойност, която е поне толкова голяма, колкото сумата на всички очаквани итерации. На практика .NET Framework (платформа) може да позволи общият брой на итерациите да превиши леко всяко изрично ограничение, конфигурирано тук.

  • Настройката на системния регистър зависи от архитектурата. За да гарантирате, че приложенията спазват конфигурираната стойност, независимо от целевата им архитектура, не забравяйте да промените както 32-битовите, така и 64-битовите регистри, както е показано по-долу.

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

За да потиснете напълно допълнителните проверки, задайте стойността в системния регистър на -1 от команден прозорец с администраторски права, както е показано по-долу.

  • ⚠️ Предупреждение: Задайте стойността в системния регистър на -1 само ако сте сигурни, че услугите, които се изпълняват на целевата машина, не обработват ненадеждни входни данни за сертификат.

  • За да зададете "страж-1", използвайте типа REG_SZ вместо типа REG_DWORD. Настройката на системния регистър зависи от архитектурата. За да гарантирате, че приложенията спазват конфигурираната стойност, независимо от целевата им архитектура, не забравяйте да промените както 32-битовите, така и 64-битовите регистри, както е показано по-долу.

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

За да върнете промените в системния регистър, изтрийте reg стойността на Pkcs12UnspecifiedPasswordIterationLimit от команден прозорец с администраторски права.

reg delete "HKLM\Software\Microsoft\.NETFramework" /v Pkcs12UnspecifiedPasswordIterationLimit /reg:32 reg delete "HKLM\Software\Microsoft\.NETFramework" /v Pkcs12UnspecifiedPasswordIterationLimit /reg:64

Бележки, специфични за Windows

В Windows .NET Framework (платформа) импортирайте сертификати чрез функцията PFXImportCertStore. Тази функция извършва своя собствена проверка, включително поставяне на собствени ограничения за максималния допустим брой итерации на PFX блоб. Тези проверки все още ще се извършват при импортиране на PFX. На . Специфичните за NET променливи на средата и ключовете от системния регистър, описани по-горе, не влияят върху начина, по който PFXImportCertStore извършва тези проверки.

Нуждаете ли се от още помощ?

Искате ли още опции?

Разгледайте ползите от абонамента, прегледайте курсовете за обучение, научете как да защитите устройството си и още.

Общностите ви помагат да задавате и отговаряте на въпроси, да давате обратна връзка и да получавате информация от експерти с богати знания.