Applies To.NET

注意: 修訂 2023 年 6 月 22 日以更新解決方案和因應措施

注意: 修訂 2023 年 6 月 15 日以更新選項 4 和 5 的運作方式 

背景

在 2023 年 6 月 13 日,Microsoft 發佈了.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

變更描述

在 2023 年 6 月 13 日之前,若.NET Framework和 .NET 提供匯入的二進位憑證 blob,.NET Framework和 .NET 通常會將 blob 的驗證及匯入委派給基礎作業系統。 例如,在 Windows 上,.NET Framework和 .NET 通常會仰賴PFXImportCertStore API 進行驗證和匯入。

自 2023 年 6 月 13 起,變更當 .NET Framework 和 .NET 提供二進位憑證 blob 進行匯入時,.NET Framework和 .NET 在某些情況下會先執行額外的驗證,然後再將 blob 交給基礎作業系統。 此額外的驗證會執行一系列的語言檢查,以判斷傳入憑證在匯入時是否會惡意耗用資源。 由於這是超出基礎作業系統正常執行的 額外 驗證,因此可能會封鎖在 2023 年 6 月 13 日變更之前成功匯入的憑證 blob。

已知回歸

  1. 如果 X.509 憑證是使用不常高的密碼反覆運算計數匯出為 PFX blob,該憑證現在可能無法匯入。 大部分的憑證匯出機構會使用介於 2,000 - 10,000 之間的反覆運算計數。 套用安全性更新之後,包含超過 600,000 個反覆運算計數的憑證將無法匯入。

  2. 如果 X.509 憑證是使用Null密碼匯出 [例如,透過X509Certificate.Export(X509ContentType.Pfx, (string)null)或無密碼X509Certificate.Export(X509ContentType.Pfx)],該憑證現在可能無法匯入。  

    附註: 上述回歸已在KB5028608中討論的 2023 年 6 月 22 日更新中解決。

  3. 如果 X.509 憑證已使用 Windows 保護 SID 專用金鑰的功能匯出為 PFX blob,該憑證現在可能無法匯入。 這會影響以下列方式建立的 PFX blob:

    • 透過 Windows 憑 證匯出精靈 ,並在精靈中指定應保護網域使用者的私人金鑰;或

    • 透過 PowerShell 的 Export-PfxCertificate Cmdlet,其中提供明確 -ProtectTo 引數;或

    • 透過提供明確 -protectto 引數的 certutil 公用程式;或

    • 透過提供PKCS12_PROTECT_TO_DOMAIN_SIDS標幟的 PFXExportCertStoreEx API。

解決&因應措施

各種因應措施存在,取決於您是否要在程式碼內的個別通話網站進行目標變更,或您想要變更單一應用程式的行為,或想要在全電腦上進行變更。

選項 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。 當指定不受信任的非 PFX blob 時,X509Certificate2(byte[]) 建構器可以安全地使用。

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 反覆運算計數、加密安全內容,以及串聯袋的反覆運算計數的總和。 如果您已使用明確反覆運算計數手動匯出 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+。  不適用於 .NET Framework

雖然 .NET 預設限制匯入作業最多隻能執行 600,000 次的密碼反覆運算,但這個限制可以使用 AppCoNtext 參數在全應用程式中設定。 這項新限制將適用于上述所有受影響 API 的叫用。

若要變更限制,請將 AppCoNtext 參數 System.Security.Cryptography.Pkcs12UnspecifiedPasswordIterationLimit 設為新限制的值。 例如,若要將限制設為 1,000,000 (100 萬) 反覆運算,請設定切換,如下所示。

  • 此數位會控制總反覆運算限制,也就是 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 (100 萬) 反覆運算,請從提升許可權的命令提示字元執行下列命令。

  • 此數位會控制 反覆運算限制,也就是 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

若要還原登錄變更,請從提升許可權的命令提示字元刪除 Pkcs12UnspecifiedPasswordIterationLimit reg 值。

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 blob 的最大允許反覆運算計數設定自己的限制。 這些檢查仍會在 PFX 匯入時進行。 ..上述的 NET 特定環境變數和登錄機碼不會影響 PFXImportCertStore 執行這些檢查的情況。

Need more help?

Want more options?

探索訂閱權益、瀏覽訓練課程、瞭解如何保護您的裝置等等。

社群可協助您詢問並回答問題、提供意見反應,以及聆聽來自具有豐富知識的專家意見。