Sql-Server

升級到 SQL Server 2017 後,錯誤消息 10314、級別 16、狀態 11 和 SAFE 程序集

  • January 21, 2020

我有一個 pre-SQL Server 2017 數據庫,我將它還原到/升級到 SQL Server 2017。在這個數據庫中,我有一個 SQLCLR 程序集。該程序集被標記為,SAFE因為它不執行任何需要更高級別權限的操作,並且數據庫已TRUSTWORTHY禁用 / OFF。SQLCLR 函式和儲存過程在遷移到 SQL Server 2017 之前按預期工作,但現在當我嘗試執行其中任何一個時,我收到以下錯誤:

消息 10314,級別 16,狀態 11,伺服器 XXXXXXXXXXX,行 YYYYYY

      嘗試載入程序集 ID ZZZZZ 時,Microsoft .NET Framework 中發生錯誤。伺服器可能資源不足,或者程序集可能不受信任。再次執行查詢,或查看文件以了解如何解決程序集信任問題。有關此錯誤的更多資訊:

      System.IO.FileLoadException:無法載入文件或程序集“{assembly_name},Version=0.0.0.0,Culture=neutral,PublicKeyToken=null”或其依賴項之一。發生與安全有關的錯誤。(來自 HRESULT 的異常:0x8013150A)

我已經確認在伺服器/實例上啟用了 CLR 集成/SQLCLR。

該錯誤是clr strict securitySQL Server 2017 中新的伺服器級配置選項的結果。這個新的安全設置不允許創建任何程序集,即使是那些標記為 的程序集,也不允許SAFE創建或載入到記憶體中執行,除非:

  • 的 Database 屬性TRUSTWORTHYON不要這樣做,因為這是不必要的安全風險)並且作為數據庫所有者的登錄名(即[dbo]使用者使用的相同 SID)需要具有UNSAFE ASSEMBLY權限(如果所有者可能已經擁有該權限)是sa sysadmin固定伺服器角色的成員可能具有CONTROL SERVER權限)。
  • 的伺服器級別配置選項clr strict security被禁用/ 0(不要這樣做,因為它是一個不必要的安全風險)
  • 程序集已簽名*,並且*您有一個相應的基於簽名的登錄名,該登錄名已被授予UNSAFE ASSEMBLY權限(執行此操作)
  • 程序集的 SHA-512 雜湊被註冊為“受信任的程序集”(絕對要這樣做,因為它存在很多問題,更不用說一開始就不需要它)

為了解決這種情況,您需要做的就是執行以下步驟(這些步驟並不困難並且提供最高級別的安全性):

  1. 在程序集所在的數據庫中創建證書

  2. 將證書(公鑰和私鑰)備份到文件(可選)

  3. 用證書籤署程序集(或程序集)

  4. 刪除私鑰(可以稍後從備份文件中恢復)(可選)

  5. 對於每個具有未簽名的附加數據庫,程序SAFE集:

  6. 要麼跳過這個子步驟(即跳到第 6 步),完成這些步驟,然後重複整個過程(這將導致每個數據庫需要一個證書),或者

  7. 執行以下操作(這將產生一個證書總數,將用於所有數據庫):

    1. 從備份文件創建相同的證書(包括私鑰!)
    2. 用證書籤署程序集(或程序集)
    3. 刪除私鑰(以後可以從備份文件中恢復)
  8. 將證書複製到[master](僅限公鑰!)

  9. 從證書創建登錄

  10. 授予基於證書的登錄UNSAFE ASSEMBLY權限

一個簡單的例子(減去可選的備份和私鑰刪除)是:

USE [{database_containing_unsigned_safe_assembly}];

CREATE CERTIFICATE [{certificate_name}]
 ENCRYPTION BY PASSWORD = '{some password}'
 WITH SUBJECT = '{simple description}',
 EXPIRY_DATE = '2099-12-31';

ADD SIGNATURE
 TO Assembly::[{assembly_name}]
 BY CERTIFICATE [{certificate_name}]
 WITH PASSWORD = '{some password}';

DECLARE @PublicKey VARBINARY(MAX),
       @SQL NVARCHAR(MAX);

SET @PublicKey = CERTENCODED(CERT_ID(N'{certificate_name}'));

SET @SQL = N'
CREATE CERTIFICATE [{certificate_name}]
 FROM BINARY = ' + CONVERT(NVARCHAR(MAX), @PublicKey, 1) + N';';
PRINT @SQL; -- DEBUG

EXEC [master].[sys].[sp_executesql] @SQL;

EXEC [master].[sys].[sp_executesql] N'
CREATE LOGIN [{login_name}]
 FROM CERTIFICATE [{certificate_name}];

GRANT UNSAFE ASSEMBLY TO [{login_name}]; -- REQUIRED!!!!
';

可以在 PasteBin 上找到一個完整的工作範例(減去備份和私鑰刪除):

避免“受信任的程序集”-展示

我的部落格文章中提供了有關為什麼應該使用證書以及為什麼不應該使用“受信任的程序集”來解決此問題的詳細說明:

SQLCLR 與 SQL Server 2017,第 4 部分:“受信任的程序集” - 失望

另外,請考慮支持我的請求,即讓 Microsoft 刪除新的“受信任的程序集”功能,因為它存在許多問題(包括安全問題),並且總體上缺乏使用它的好處:

可信程序集比證書更成問題但功能更少 - 請刪除

引用自:https://dba.stackexchange.com/questions/186957