注: 自分の組織と、予定表の共有相手であるユーザーの組織が Office 365 または Exchange を介してフェデレーションされている場合、招待には 2 つのボタンもあります。解決と回避策を更新するために、2023 年 6 月 22 日に改訂されました
注: 自分の組織と、予定表の共有相手であるユーザーの組織が Office 365 または Exchange を介してフェデレーションされている場合、招待には 2 つのボタンもあります。オプション 4 と 5 の回避策を更新するために、2023 年 6 月 15 日に改訂されました
背景
2023 年 6 月 13 日、Microsoft は、ランタイムが X.509 証明書をインポートする方法に影響を与える、.NET Framework と .NET のセキュリティ更新プログラムをリリースしました。 これらの変更により、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
変更の説明
2023 年 6 月 13 日より前は、.NET Frameworkと .NET にインポート用のバイナリ証明書 BLOB が表示される場合、.NET Framework と .NET は通常、BLOB の検証とインポートを基になる OS に委任していました。 たとえば、Windows では、.NET Frameworkと .NET は通常、検証とインポートのために PFXImportCertStore API に依存します。
2023 年 6 月 13 日の時点で、.NET Frameworkと .NET にインポート用のバイナリ証明書 BLOB が表示されると、.NET Frameworkと .NET は、状況によっては、基になる OS に BLOB を渡す前に追加の検証を実行します。 この追加の検証では、一連のヒューリスティック チェックを実行して、受信証明書がインポート時にリソースを悪意を持って枯渇するかどうかを判断します。 これは、基になる OS が通常実行する以外の 追加 の検証であるため、2023 年 6 月 13 日の変更より前に正常にインポートされた証明書 BLOB がブロックされる可能性があります。
既知の回帰
-
X.509 証明書が、一般的に高いパスワード イテレーション数を使用して PFX BLOB としてエクスポートされている場合、その証明書のインポートに失敗する可能性があります。 ほとんどの証明書エクスポート機能では、2,000 から 10,000 の間のイテレーション数が使用されます。 セキュリティ更新プログラムが適用されると、イテレーション数が 600,000 を超える証明書のインポートは失敗します。
-
X.509 証明書が null パスワード (例:X509Certificate.Export(X509ContentType.Pfx, (string)null)またはパスワードレスX509Certificate.Export(X509ContentType.Pfx)]を使用してエクスポートされた場合、その証明書はインポートに失敗する可能性があります。
注: 上記の回帰は、KB5028608 で説明されている 2023 年 6 月 22 日の更新プログラムで対処されています。
-
WINDOWS の機能を使用して X.509 証明書が PFX BLOB としてエクスポートされ、SID に秘密キーを保護している場合、その証明書のインポートに失敗する可能性があります。 これは、次の方法で作成された PFX BLOB に影響します。
-
Windows の 証明書エクスポート ウィザード を使用して、ウィザードで秘密キーをドメイン ユーザーに保護するように指定します。または
-
明示的な -ProtectTo 引数が指定されている PowerShell の Export-PfxCertificate コマンドレットを使用します。または
-
明示的な -protectto 引数が指定されている certutil ユーティリティを使用します。または
-
PKCS12_PROTECT_TO_DOMAIN_SIDS フラグが指定されている PFXExportCertStoreEx API を使用します。
-
解決策&回避策
コード内の個々の呼び出しサイトで対象を変更するか、1 つのアプリケーションの動作を変更するか、コンピューター全体の変更を行うかに応じて、さまざまな回避策が存在します。
オプション 1 (推奨) - 更新されたパッチをインストールする
注: これは、一般的に報告される顧客の回帰に対処し、アプリケーションにコードを変更する必要がないため、推奨されるオプションです。
適用可能性: このオプションは、.NET Frameworkと .NET のすべてのバージョンに適用されます。
この問題は、KB5028608 で説明されている 2023 年 6 月 22 日の更新プログラムで対処されています。
Microsoft では、2023 年 6 月 13 日までに導入された回帰が発生しているお客様は、このドキュメントの後半に記載されている回避策を試す前に、この更新されたパッチのインストールを試みるようにお勧めします。
オプション 2 - 通話サイトの変更
適用可能性: このオプションは、.NET Frameworkと .NET のすべてのバージョンに適用されます。
インポートする BLOB が信頼できるかどうかを検討します。 たとえば、BLOB は、制御下のデータベースや構成ファイルなどの信頼できる場所から取得されたか、認証されていないクライアントまたは特権のないクライアントによって行われたネットワーク要求を介して提供されたのですか?
Microsoft では、認証されていないクライアントまたは特権のないクライアントによって提供される PFX BLOB はインポートしないことを強くお勧めします。これらの BLOB には悪意のあるリソース枯渇動作が含まれている可能性があります。
信頼されていないパーティから提供された公開キー証明書 BLOB をインポートする必要がある場合は、次のコードを使用して、このような BLOB を安全にインポートできます。 このサンプル コードでは、GetCertContentType メソッドを使用して、証明書 BLOB の基になる種類を特定し、公開キー証明書 BLOB のみをインポートする必要がある場合に PFX BLOB を拒否します。 X509Certificate2(byte[]) コンストラクターは、信頼されていない PFX 以外の BLOB を指定した場合に使用しても安全です。
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 が信頼できると判断した場合は、別のコンストラクター オーバーロードを呼び出すことで、2023 年 6 月 13 日のセキュリティ リリースによって実行される追加の検証チェックを抑制できます。 たとえば、文字列パスワード引数を受け取り、引数値に 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 (100 万) のイテレーションに制限を設定するには、次に示すように環境変数を設定します。
-
この数値は、MAC イテレーション数、暗号化された安全なコンテンツ、およびシュラウド されたバッグの反復回数の合計である 合計 反復制限を制御します。 明示的な反復回数<iter_count>を使用して PFX を手動でエクスポートした場合 (たとえば、openssl pkcs12 -export -iter <iter_count>経由) で、その PFX BLOB をインポートする場合は、この環境変数を、少なくとも期待される反復の合計と同じ大きさに設定します。 実際には、.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 (100 万) のイテレーションに制限を設定するには、次に示すようにスイッチを設定します。
-
この数値は、MAC イテレーション数、暗号化された安全なコンテンツ、およびシュラウド されたバッグの反復回数の合計である合計反復制限を制御します。 明示的な反復回数<iter_count>を使用して PFX を手動でエクスポートした場合 (たとえば、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 ランタイム構成設定」のドキュメント ページを参照してください。
追加のチェックを完全に抑制するには、次に示すように、構成スイッチを特殊な 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 - レジストリを介した追加の検証マシン全体の変更または抑制 (.NET Frameworkの Windows のみ)
適用可能性: このオプションは、すべてのバージョンの.NET Frameworkにのみ適用されます。 .NET 6.0 以降には適用されません。
.NET Framework既定では、インポート操作がパスワードの反復回数を 600,000 回以下に制限しますが、この制限は HKLM レジストリを使用してマシン全体で構成できます。 この新しい制限は、上記の影響を受ける API のすべての呼び出しに適用されます。
制限を変更するには、レジストリ キーのHKLM\Software\Microsoft\.NETFrameworkで、Pkcs12UnspecifiedPasswordIterationLimit値を新しい制限に設定します。 たとえば、制限を 1,000,000 (100 万) のイテレーションに設定するには、管理者特権のコマンド プロンプトから次のようにコマンドを実行します。
-
この数値は、MAC イテレーション数、暗号化された安全なコンテンツ、およびシュラウド されたバッグの反復回数の合計である 合計 反復制限を制御します。 明示的な反復回数の<iter_count>を使用して PFX を手動でエクスポートした場合 (たとえば、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 Sentinel を設定するには、REG_DWORD型の代わりに REG_SZ 型を使用します。 レジストリ設定はアーキテクチャに依存します。 ターゲット アーキテクチャに関係なく、アプリケーションで構成された値が確実に確認されるようにするには、次に示すように、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 では、PFXImportCertStore 関数を使用して証明書をインポート.NET Framework。 この関数は、PFX BLOB の最大許容反復回数に独自の制限を設定するなど、独自の検証を実行します。 これらのチェックは、PFX インポート時に引き続き行われます。 。上記の NET 固有の環境変数とレジストリ キーは、PFXImportCertStore がこれらのチェックを実行する方法には影響しません。