Примітка: Виправлено 22 червня 2023 р. для оновлення роздільної здатності та способів вирішення
Примітка: Виправлено 15 червня 2023 р. для оновлення параметрів 4 та 5
Фоновому режимі
13 червня 2023 року корпорація Майкрософт випустила оновлення системи безпеки для .NET Framework та .NET, що впливає на імпорт сертифікатів 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 представлено BLOB-об'єкт двійкового сертифіката для імпорту, .NET Framework та .NET зазвичай делегують перевірку та імпорт BLOB-об'єктів до базової ОС. Наприклад, у Windows .NET Framework та .NET зазвичай використовують API PFXImportCertStore для перевірки та імпорту.
Станом на 13 червня 2023 року змінюється, коли .NET Framework та .NET представлено BLOB-об'єкт двійкового сертифіката для імпорту, .NET Framework і .NET в деяких випадках виконуватимуть додаткову перевірку, перш ніж передати BLOB-об'єкт в основну ОС. Ця додаткова перевірка виконує ряд евристичних перевірок, щоб визначити, чи вхідний сертифікат буде зловмисно вичерпати ресурси під час імпорту. Оскільки це додаткова перевірка, окрім того, що зазвичай виконує базова ОС, вона може заблокувати зміни, імпортовані до 13 червня 2023 року.
Відомі регресії
-
Якщо сертифікат X.509 експортовано як BLOB-об'єкт PFX із використанням надзвичайно високої кількості ітерацій паролів, цей сертифікат може не імпортуватися. У більшості засобів експорту сертифікатів використовується кількість ітерацій у діапазоні від 2000 до 10 000. Після застосування оновлення системи безпеки імпортування завершиться помилкою для сертифікатів, які містять кількість ітерацій, які перевищують 600 000.
-
Якщо сертифікат X.509 експортовано з використанням null-пароля [наприклад, за допомогоюX509Certificate.Export(X509ContentType.Pfx, (string)null)або без пароляX509Certificate.Export(X509ContentType.Pfx)], цей сертифікат може не імпортуватися.
Примітка.: Вищезазначена регресія була розглянута в оновленні від 22 червня 2023 року, обговорюваному в KB5028608.
-
Якщо сертифікат X.509 експортовано як BLOB-об'єкт PFX за допомогою можливості Windows захистити закритий ключ до SID, цей сертифікат може не імпортуватися. Це вплине на PFX блоби, створені таким чином:
-
За допомогою майстра експорту сертифікатів Windows і вказавши в майстрі, що приватний ключ має бути захищено для користувача домену; Або
-
За допомогою командлета PowerShell Export-PfxCertificate , де надається явний аргумент -ProtectTo ; Або
-
За допомогою утиліти certutil , де надається явний аргумент -protectto ; Або
-
За допомогою API PFXExportCertStoreEx , де вказано позначку PKCS12_PROTECT_TO_DOMAIN_SIDS.
-
Вирішення & способи вирішення
Існують різні способи вирішення, залежно від того, чи потрібно вносити цільові зміни на окремих сайтах викликів у коді, змінити поведінку однієї програми або внести зміни на рівні комп'ютера.
Варіант 1 (рекомендований) – інсталяція оновленого виправлення
Примітка.: Це рекомендований варіант, оскільки він вирішує часто повідомлені регресії клієнтів і не вимагає будь-яких змін коду в програмі.
Застосовність. Цей параметр застосовується до всіх версій .NET Framework і .NET.
Цю проблему вирішено в оновленні KB5028608 від 22 червня 2023 р.
Корпорація Майкрософт рекомендує користувачам, у яких спостерігається регресія до 13 червня 2023 р., інсталювати це оновлене виправлення, перш ніж спробувати способи вирішення, наведені далі в цьому документі.
Варіант 2. Змінення сайту виклику
Застосовність. Цей параметр застосовується до всіх версій .NET Framework і .NET.
Подумайте, чи є BLOB-об'єкт, який імпортується, надійним. Наприклад, чи отримано BLOB-об'єкт із надійного розташування, наприклад із бази даних чи файлу конфігурації під вашим елементом керування, або чи надавався він через мережевий запит, зроблений неавтентифікованим або непривілейованим клієнтом?
Корпорація Майкрософт наполегливо рекомендує не імпортувати PFX-блоби, надані неавтентифікованими або непривілейованими клієнтами, оскільки ці блоби можуть містити шкідливу поведінку виснаження ресурсів.
Якщо вам потрібно імпортувати BLOB-об'єкт сертифіката відкритого ключа, наданий ненадійною стороною, можна скористатися наведеним нижче кодом, щоб безпечно імпортувати такий BLOB-об'єкт. Цей зразок коду використовує метод GetCertContentType, щоб визначити основний тип BLOB-об'єкта сертифіката, і відхиляє BLOB-об'єкт PFX у випадках, коли ви очікуєте імпортувати лише BLOB-об'єкт сертифіката відкритого ключа. Конструктор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);
}
}
Якщо потрібно імпортувати BLOB-об'єкт сертифіката закритого ключа без паролем і ви визначили, що 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>) і хочете імпортувати цей BLOB-об'єкт PFX, установіть для цієї змінної середовища значення принаймні такого ж великого, як сума всіх очікуваних ітерацій. На практиці .NET Framework та .NET можуть дозволити загальній кількості ітерацій трохи перевищити явне обмеження, настроєні тут.
COMPlus_Pkcs12UnspecifiedPasswordIterationLimit=1000000
Щоб повністю заборонити додаткові перевірки, установіть для змінної середовища спеціальне значення sentinel -1, як показано нижче.
-
⚠️ Увага! Установіть для змінної середовища значення -1, лише якщо ви впевнені, що цільовий застосунок не обробляє ввід ненадійного сертифіката.
COMPlus_Pkcs12UnspecifiedPasswordIterationLimit=-1
Варіант 4. Змінення або заборона додаткової перевірки за допомогою AppContext
Застосовність: цей параметр застосовується лише до .NET 6.0+. Вона не стосується .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>) і хочете імпортувати цей BLOB-об'єкт PFX, установіть для цієї змінної середовища значення принаймні такого ж великого, як сума всіх очікуваних ітерацій. На практиці .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 configuration settings.
Щоб повністю заборонити додаткові перевірки, установіть для параметра конфігурації спеціальне значення sentinel -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>) і хочете імпортувати цей BLOB-об'єкт PFX, установіть для цього значення реєстру значення принаймні такого розміру, як сума всіх очікуваних ітерацій. На практиці .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 sentinel, введіть 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
Щоб відновити зміни реєстру, видаліть значення реєстру 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. Ця функція виконує власну перевірку, включно з розміщенням власних обмежень на максимальну дозволену кількість ітерацій BLOB-об'єктів PFX. Ці перевірки й надалі виконуватимуться під час імпорту PFX. . Net-specific environment variables and registry keys described above do not impact how PFXImportCertStore perform these checks.