Lưu ý: Đã sửa đổi ngày 22 tháng 6 năm 2023 để cập nhật giải pháp và giải pháp thay thế

Lưu ý: Đã sửa đổi vào ngày 15 tháng 6 năm 2023 để cập nhật các tùy chọn 4 và 5 

Nền

Vào ngày 13 tháng 6 năm 2023, Microsoft đã phát hành một bản cập nhật bảo mật cho .NET Framework và .NET ảnh hưởng đến cách thời gian chạy nhập chứng chỉ X.509. Những thay đổi này có thể gây ra X.509 chứng chỉ nhập khẩu để ném CryptographicException trong các trường hợp nhập khẩu đã thành công trước khi cập nhật.

Tài liệu này mô tả thay đổi và giải pháp thay thế sẵn dùng cho các ứng dụng bị ảnh hưởng.

Phần mềm bị ảnh hưởng

  • .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 bị ảnh hưởng

Mô tả thay đổi

Trước ngày 13 tháng 6 năm 2023, thay đổi khi .NET Framework và .NET được cung cấp cùng với blob chứng chỉ nhị phân để nhập, .NET Framework và .NET thường sẽ ủy quyền xác thực và nhập blob cho HĐH cơ sở. Ví dụ: trên Windows, .NET Framework và .NET thường dựa vào API PFXImportCertStore để xác thực và nhập.

Kể từ ngày 13 tháng 6 năm 2023, thay đổi khi .NET Framework và .NET được cung cấp cùng với blob chứng chỉ nhị phân để nhập, .NET Framework và .NET sẽ thực hiện xác thực bổ sung trước khi giao blob cho HĐH cơ sở. Xác thực bổ sung này thực hiện một loạt kiểm tra định kỳ để xác định xem liệu chứng chỉ đến có gây ra tình trạng làm cạn kiệt tài nguyên khi nhập hay không. Vì đây là xác thực bổ sung ngoài những gì HĐH cơ bản thường thực hiện, nó có thể chặn các blobs chứng chỉ đã được nhập thành công trước ngày 13 tháng 6 năm 2023, thay đổi.

Hồi quy đã biết

  1. Nếu chứng chỉ X.509 đã được xuất dưới dạng blob PFX bằng cách sử dụng số lần lần hiển thị mật khẩu cao hiếm gặp, chứng chỉ đó có thể không nhập được. Hầu hết các cơ sở xuất chứng chỉ sử dụng số lần hiển thị nằm trong khoảng từ 2.000 đến 10.000. Sau khi áp dụng bản cập nhật bảo mật, quá trình nhập sẽ không thành công đối với chứng chỉ có chứa số lần thử lớn hơn 600.000.

  2. Nếu chứng chỉ X.509 đã được xuất bằng mật khẩu null [ví dụ: thông quaX509Certificate.Export(X509ContentType.Pfx, (string)null)hoặcX509Certificate.Export(X509ContentType.Pfx)]không có mật khẩu, chứng chỉ đó có thể không nhập được.  

    Lưu ý: Hồi quy trên đã được giải quyết trong Bản cập nhật ngày 22 tháng 6 năm 2023 được thảo luận trong KB5028608.

  3. Nếu chứng chỉ X.509 đã được xuất dưới dạng blob PFX bằng cách sử dụng khả năng bảo vệ khóa riêng cho một SID, chứng chỉ đó có thể không nhập được. Điều này sẽ ảnh hưởng đến các blobs PFX được tạo theo cách sau:

    • Thông qua Trình hướng dẫn Xuất Chứng chỉ của Windows và chỉ định trong trình hướng dẫn rằng khóa riêng sẽ được bảo vệ cho người dùng miền; Hoặc

    • Thông qua lệnh ghép ngắn Export-PfxCertificate của PowerShell, nơi cung cấp đối số -ProtectTo định rõ ràng; Hoặc

    • Thông qua các tiện ích certutil nơi một đối số -protectto rõ ràng được cung cấp; Hoặc

    • Thông qua API PFXExportCertStoreEx , nơi cờ báo PKCS12_PROTECT_TO_DOMAIN_SIDS được cung cấp.

Giải pháp & giải pháp thay thế

Tồn tại nhiều giải pháp thay thế khác nhau, tùy thuộc vào việc bạn muốn thực hiện thay đổi mục tiêu tại các site cuộc gọi cá nhân trong mã của bạn, hoặc bạn muốn thay đổi hành vi của một ứng dụng duy nhất, hoặc bạn muốn thực hiện thay đổi trên toàn máy.

Tùy chọn 1 (ưu tiên) - Cài đặt bản vá đã cập nhật

Lưu ý: Đây là tùy chọn được ưa thích vì nó đề cập đến hồi quy khách hàng thường được báo cáo và không yêu cầu bất kỳ thay đổi mã nào đối với ứng dụng.

Khả năng áp dụng: Tùy chọn này áp dụng cho tất cả các phiên bản của .NET Framework và .NET.

Sự cố này đã được khắc phục trong Bản cập nhật ngày 22 tháng 6 năm 2023 được thảo luận trong KB5028608.

Microsoft khuyên khách hàng đang gặp phải tình trạng hồi quy được giới thiệu vào ngày 13 tháng 6 năm 2023, hãy thử cài đặt bản vá được cập nhật này trước khi thử các giải pháp thay thế được liệt kê ở phần sau trong tài liệu này.

Tùy chọn 2 - Sửa đổi site cuộc gọi

Khả năng áp dụng: Tùy chọn này áp dụng cho tất cả các phiên bản của .NET Framework và .NET.

Hãy cân nhắc xem liệu blob bạn đang nhập có đáng tin cậy hay không. Ví dụ: blob được truy xuất từ một vị trí tin cậy, chẳng hạn như một cơ sở dữ liệu hoặc tệp cấu hình dưới quyền kiểm soát của bạn hay được cung cấp thông qua một yêu cầu mạng được thực hiện bởi một máy khách không xác thực hoặc không có bảo mật?

Microsoft khuyên bạn không nhập blobs PFX cung cấp cho bạn bởi các khách hàng không xác thực hoặc không có bảo mật, vì các blobs này có thể chứa hành vi cạn kiệt tài nguyên độc hại.

Nếu bạn cần nhập một blob chứng chỉ khóa công cộng được cung cấp cho bạn bởi một bên không đáng tin cậy, bạn có thể sử dụng mã sau đây để nhập một cách an toàn blob như vậy. Mã mẫu này sử dụng phương pháp GetCertContentType để xác định loại blob chứng chỉ cơ sở là gì và sẽ từ chối blob PFX trong trường hợp bạn chỉ muốn nhập blob chứng chỉ khóa công cộng. CácX509Certificate2(byte[]) xây dựng là an toàn để sử dụng khi không đáng tin cậy không PFX blobs.

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);
    }
} 

Nếu bạn cần nhập blob chứng chỉ khóa riêng không mật khẩu và bạn đã xác định rằng blob đó là đáng tin cậy, bạn có thể chặn kiểm tra xác thực bổ sung được thực hiện bởi bản phát hành bảo mật ngày 13 tháng 6 năm 2023 bằng cách gọi quá tải nhà xây dựng khác. Ví dụ, bạn có thể gọi quá tải nhà xây dựng chấp nhận một đối số mật khẩu chuỗi và truyền null cho giá trị đối số. 

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);

Tùy chọn 3 - Sửa đổi hoặc bỏ xác thực bổ sung bằng cách sử dụng biến môi trường

Khả năng áp dụng: Tùy chọn này chỉ áp dụng cho tất cả các phiên bản của .NET Framework.  Điều này không áp dụng cho .NET 6.0+.

Mặc dù .NET Framework theo mặc định giới hạn các thao tác nhập để thực hiện không quá 600.000 lần nhập mật khẩu, giới hạn này có thể được đặt cấu hình trên toàn ứng dụng hoặc trên toàn máy bằng cách sử dụng biến môi trường. Giới hạn mới này sẽ áp dụng cho tất cả các gọi của API bị ảnh hưởng được liệt kê ở trên.

Để thay đổi giới hạn, hãy đặt biến môiCOMPlus_Pkcs12UnspecifiedPasswordIterationLimitthành giá trị của giới hạn mới. Ví dụ, để đặt giới hạn là 1.000.000 (một triệu), hãy đặt biến môi trường như minh họa dưới đây.

  • Số này kiểm soát giới hạn lặp tổng, là tổng số lần lặp MAC, nội dung an toàn được mã hóa và số lần lặp của túi được định tuyến. Nếu bạn đã xuất PFX theo cách thủ công bằng cách sử dụng một số lần lần hiển thị <iter_count> (ví dụ: thông qua openssl pkcs12 -export -iter <iter_count>) và muốn nhập blob PFX đó, hãy đặt biến môi trường này thành giá trị ít nhất lớn bằng tổng của tất cả các lần lần thử dự kiến. Trên thực tế, .NET Framework và .NET có thể cho phép tổng số lần thử vượt quá một chút bất kỳ giới hạn rõ ràng nào được đặt cấu hình ở đây.

COMPlus_Pkcs12UnspecifiedPasswordIterationLimit=1000000

Để ngăn chặn kiểm tra bổ sung hoàn toàn, thiết lập biến môi trường giá trị sentinel đặc biệt -1, như minh họa dưới đây.

  • ⚠️ Cảnh báo: Chỉ đặt giá trị biến môi trường thành -1 nếu bạn chắc chắn rằng ứng dụng đích không xử lý đầu vào chứng chỉ không đáng tin cậy.

COMPlus_Pkcs12UnspecifiedPasswordIterationLimit=-1

Tùy chọn 4 - Sửa đổi hoặc bỏ xác thực bổ sung bằng appContext

Khả năng áp dụng: Tùy chọn này áp dụng cho .NET 6.0+only.  Điều này không áp dụng cho .NET Framework

Mặc dù .NET theo mặc định giới hạn nhập các thao tác để thực hiện không quá 600.000 lần hiển thị mật khẩu, giới hạn này có thể được đặt cấu hình trên toàn bộ ứng dụng bằng cách sử dụng khóa chuyển AppContext. Giới hạn mới này sẽ áp dụng cho tất cả các gọi của API bị ảnh hưởng được liệt kê ở trên.

Để thay đổi giới hạn, hãy đặt khóa chuyển AppContext System.Security.Cryptography.Pkcs12UnspecifiedPasswordIterationLimit thành giá trị của giới hạn mới. Ví dụ: để đặt giới hạn là 1.000.000 (một triệu), hãy đặt khóa chuyển như minh họa dưới đây.

  • Số này kiểm soát giới hạn lặp tổng, là tổng số lần lặp MAC, nội dung an toàn được mã hóa và số lần lặp của túi được định tuyến. Nếu bạn đã xuất PFX theo cách thủ công bằng cách sử dụng một số lần lần hiển thị <iter_count> (ví dụ: thông qua openssl pkcs12 -export -iter <iter_count>) và muốn nhập blob PFX đó, hãy đặt biến môi trường này thành giá trị ít nhất lớn bằng tổng của tất cả các lần lần thử dự kiến. Trên thực tế, .NET có thể cho phép tổng số lần thử vượt quá một chút so với bất kỳ giới hạn rõ ràng nào được đặt cấu hình ở đây.

Để đặt khóa chuyển trong tệp dự án của ứng dụng (.csproj hoặc .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>

Ngoài ra, bạn có thể đặt một tệp có tên là runtimeconfig.template.json với nội dung sau đây trong cùng một thư mục chứa tệp dự án của ứng dụng:

{

     "configProperties": {

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

      }

}

Để biết thêm thông tin về cách thay đổi cài đặt cấu hình thời gian chạy .NET, hãy xem trang tài liệu cài đặt cấu hình .NET Runtime.

Để bỏ hoàn toàn kiểm tra bổ sung, hãy đặt cấu hình chuyển đổi giá trị sentinel đặc biệt -1, như minh họa dưới đây.

⚠️ Cảnh báo: Chỉ đặt khóa chuyển AppContext thành -1 nếu bạn chắc chắn rằng ứng dụng đích không xử lý đầu vào chứng chỉ không đáng tin cậy.

Trong tệp dự án của ứng dụng (.csproj hoặc .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>

Hoặc trong tệp runtimeconfig.template.json:

{

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

     }

}

Tùy chọn 5 - Sửa đổi hoặc bỏ xác thực bổ sung trên toàn bộ máy thông qua sổ đăng ký (Windows-only cho .NET Framework)

Khả năng áp dụng: Tùy chọn này chỉ áp dụng cho tất cả các phiên bản của .NET Framework.  Điều này không áp dụng cho .NET 6.0+.

Mặc dù .NET Framework theo mặc định giới hạn hoạt động nhập không quá 600.000 lần hiển thị mật khẩu, giới hạn này có thể được đặt cấu hình trên toàn máy bằng cách sử dụng sổ đăng ký HKLM. Giới hạn mới này sẽ áp dụng cho tất cả các gọi của API bị ảnh hưởng được liệt kê ở trên.

Để thay đổi giới hạn, bên dưới khóa đăng kýHKLM\Software\Microsoft\.NETFramework, hãy đặt giáPkcs12UnspecifiedPasswordIterationLimitcho giới hạn mới. Ví dụ: để đặt giới hạn là 1.000.000 lần đọc (một triệu), hãy chạy các lệnh như minh họa dưới đây từ dấu nhắc lệnh mức cao.

  • Số này kiểm soát giới hạn lặp tổng, là tổng số lần lặp MAC, nội dung an toàn được mã hóa và số lần lặp của túi được định tuyến. Nếu bạn đã xuất PFX theo cách thủ công bằng cách sử dụng một số lần hiển thị lần hiển thị <iter_count> (ví dụ: thông qua openssl pkcs12 -export -iter <iter_count>) và muốn nhập blob PFX đó, hãy đặt giá trị đăng ký này thành một giá trị ít nhất lớn bằng tổng của tất cả các lần lần thử dự kiến. Trên thực tế, .NET Framework có thể cho phép tổng số lần thử vượt quá một chút so với bất kỳ giới hạn rõ ràng nào được đặt cấu hình ở đây.

  • Thiết đặt đăng ký phụ thuộc vào kiến trúc. Để đảm bảo rằng các ứng dụng quan sát giá trị đã đặt cấu hình của bạn bất kể cấu trúc mục tiêu của chúng là gì, hãy nhớ sửa đổi cả hai bản đăng ký 32 bit và 64 bit, như minh họa dưới đây.

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

Để bỏ hoàn toàn kiểm tra bổ sung, hãy đặt giá trị sổ đăng ký thành -1 từ lời nhắc chỉ lệnh mức cao, như minh họa dưới đây.

  • ⚠️ Cảnh báo: Chỉ đặt giá trị sổ đăng ký thành -1 nếu bạn chắc chắn rằng các dịch vụ chạy trên máy đích không xử lý đầu vào chứng chỉ không đáng tin cậy.

  • Để đặt sentinel -1, hãy sử dụng kiểu REG_SZ thay vì kiểu REG_DWORD này. Thiết đặt đăng ký phụ thuộc vào kiến trúc. Để đảm bảo rằng các ứng dụng quan sát giá trị đã đặt cấu hình của bạn bất kể cấu trúc mục tiêu của chúng là gì, hãy nhớ sửa đổi cả hai bản đăng ký 32 bit và 64 bit, như minh họa dưới đây.

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

Để hoàn nguyên những thay đổi trong sổ đăng ký, hãy xóa giá trị reg Pkcs12UnspecifiedPasswordIterationLimit khỏi lời nhắc chỉ lệnh mức cao.

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

Ghi chú dành riêng cho Windows

Trên Windows, .NET Framework nhập chứng chỉ thông qua hàm PFXImportCertStore. Hàm này thực hiện xác thực riêng của mình, bao gồm đặt các giới hạn riêng của mình trên số lần lần hiển thị cho phép tối đa của blob PFX. Những kiểm tra này vẫn sẽ được thực hiện khi nhập khẩu PFX. Các . Các biến môi trường và khóa đăng ký cụ thể của NET được mô tả ở trên không ảnh hưởng đến cách PFXImportCertStore thực hiện các kiểm tra này.

Bạn cần thêm trợ giúp?

Bạn muốn xem các tùy chọn khác?

Khám phá các lợi ích của gói đăng ký, xem qua các khóa đào tạo, tìm hiểu cách bảo mật thiết bị của bạn và hơn thế nữa.

Cộng đồng giúp bạn đặt và trả lời các câu hỏi, cung cấp phản hồi và lắng nghe ý kiến từ các chuyên gia có kiến thức phong phú.