如何建立 In-Memory OLTP 應用程式控制與管理安裝程式政策

適用於:SQL Server

SQL Server 為每個原生編譯的表格與儲存程序編譯並連結動態連結函式庫(DLL),其中包含這些物件的原生 C 程式碼實作。 雖然 In-Memory OLTP DLL 是動態產生的,但在需要強制執行程式碼完整性的環境中,這些檔案仍可能帶來挑戰。

什麼是 HkDllGen?

在 SQL Server 2022(16.x)累積更新 17 及之後版本中,In-Memory OLTP 功能包含 Hekaton DLL 產生器,或稱 HkDllGen。 若沒有 HkDllGen,SQL Server 會在內部sqlservr.exe產生 C 原始碼並啟動編譯器,該編譯器會呼叫連結器來建立 In-Memory OLTP DLL。 啟用外部產生功能時,SQL Server 會匯出序列化的物件中繼資料,並啟動由 Microsoft 簽署的 hkdllgen.exe。 HkDllGen 會驗證並匯入該中繼資料,自行產生 C 原始碼,並啟動編譯器和連結器。

為了強制這些 DLL 的程式碼完整性,使用 AppLocker 將已簽署hkdllgen.exe的 Microsoft 指定為受管理安裝程式,並在 App Control for Business 政策(前身為 Windows Defender Application Control (WDAC))中啟用託管安裝程式的信任。 Windows 會記錄產生的 DLL 來自 HkDllGen 程序樹,讓 App Control 根據其管理安裝程式來源信任它們。

HkDllGen 是朝向符合記憶體內部 OLTP 的法規要求(包括 程式碼完整性)邁出的第一步。 在這種情況下,程式碼完整性確保 Windows 能為每個產生的 DLL 建立可信來源,並在 SQL Server 載入時評估該信任。 產生的 DLL 沒有 Authenticode 簽名。 Windows 會根據其建立方式來信任它。

受管理的安裝程式如何運作?

受管理安裝程式會使用 AppLocker 中的特殊規則集合,指定貴組織信任的二進位檔作為應用程式安裝的授權來源。 當其中一個受信任的二進位檔執行時,Windows 會監視二進位檔的進程(以及它啟動的任何子進程),並監看正在寫入磁碟的檔案。 隨著檔案的寫入,宣告或標籤會被新增到檔案中,表示其來源於受管控的安裝程式。

來源宣告是一種由核心管理的延伸屬性。 這不是 Authenticode 簽名,也不會改變產生的 DLL 的發佈者或簽署狀態。

透過使用 AppLocker,企業版應用程式控制(前稱 Windows Defender Application Control,或 WDAC)可以透過在 App Control 政策中加入 Enabled:Managed Installer 選項,設定為信任受管理安裝程式安裝的檔案。 當你設定這個選項時,App Control 會在判斷是否允許執行二進位檔時,檢查受管理安裝器的來源資訊。 只要二進位檔沒有拒絕規則,App Control 就允許它完全根據其受控安裝程式來源執行。 AppLocker 也會控制由其指定為受管理安裝程式所安裝的可執行檔之執行,但它不像 WDAC 那樣,為可執行檔和 DLL 提供信任鏈。 本文將說明如何指定並設定 HkDllGen 程序作為一個受管理安裝程式,讓 AppLocker 和 WDAC 都能使用。

啟用 Hekaton DLL 產生器

例

此範例透過使用 sp_configureexternal xtp dll gen util enabled 選項使 Hekaton DLL 產生器得以實現。 建立一個測試資料庫和一個測試記憶體優化的表格。

  1. 建立測試資料庫。

    USE master;
    GO
    
    EXECUTE sp_configure 'external xtp dll gen util enabled', 1;
    RECONFIGURE;
    GO
    
    CREATE DATABASE HekatonDbForTesting ON
    PRIMARY (
        NAME = N'HekatonDbForTesting_Data',
        FILENAME = N'<path-to-data-directory>\HekatonDbForTesting_Data.mdf'
    ),
    FILEGROUP [HekatonDbForTestin_XTP_FG] CONTAINS MEMORY_OPTIMIZED_DATA (
        NAME = HekatonDbForTesting_XTP_CHKPOINT,
        FILENAME = N'<path-to-data-directory>\HekatonDbForTesting_XTP_CHKPOINT'
    )
    LOG ON (
        NAME = N'HekatonDbForTesting_log',
        FILENAME = N'<Path_To_Log_Directory>\HekatonDbForTesting_Log.ldf'
    );
    GO
    
  2. 在測試資料庫中建立測試數據表。

    USE HekatonDbForTesting;
    GO
    
    CREATE TABLE dbo.TestCustomerTable
    (
        CustomerId INT NOT NULL
            PRIMARY KEY NONCLUSTERED HASH WITH (BUCKET_COUNT = 1000000),
        FirstName NVARCHAR (50) NOT NULL,
        LastName NVARCHAR (50) NOT NULL
    )
    WITH (MEMORY_OPTIMIZED = ON, DURABILITY = SCHEMA_AND_DATA);
    GO
    
  3. 在 <path-to-data-directory>\xtp\<database_id> 子目錄中,會為每個由 HkDllGen 產生的 DLL 一併建立一個 .gen 檔案。 此檔案擷取 HkDllGen 輸出,成功編譯後通常長度為零。 其存在表示外部產生器已被調用。 產生的 DLL 並沒有 Authenticode 簽名。 為了讓 Windows 信任根據來源產生的 DLL 檔案,你需要管理安裝程式追蹤和應用程式控制政策。

現有的 DLL 不會事後回溯取得受控安裝程式來源資訊。 在驗證政策時,管理安裝器追蹤啟動後,產生新的 DLL。

建立 In-Memory OLTP AppLocker 及管理安裝程式政策的步驟

你不能用 GPO 編輯器gpedit.msc裡的 AppLocker 政策建立介面()或 AppLocker PowerShell 的 cmdlets 來建立管理安裝規則集合的規則。 不過,你可以使用 XML 或文字編輯器,將 EXE 規則收集政策轉換成受管理的安裝程式規則集合。

重要

你需要先制定 AppLocker 政策,才能將 Hekaton DLL 產生的執行檔加入伺服器的 AppLocker Control 政策設定。 若沒有政策,Windows Defender可能會阻擋基本作業系統功能。 欲了解更多關於建立、測試及維護應用程式控制政策的資訊,請參閱 AppLocker 部署指南。

本文其餘的範例適用於 Windows Server 2022 以及 Windows 11 及更新版本。

為了驗證伺服器的 AppLocker Control 政策設定中至少存在一個 exe 規則集合,請執行以下 PowerShell 指令:

Get-AppLockerPolicy -Effective

或者,執行以下指令將有效政策的輸出儲存為 XML 檔案以便查看:

Get-AppLockerPolicy -Effective -Xml > effective_app_policy.xml

以下步驟將逐步說明如何建立並套用可用於本地伺服器的政策。 透過這些步驟產生的受管理安裝程式政策可以合併成 GPO 範圍的政策,並分發給環境中所有 SQL Server 實例,或套用到單一伺服器的本地政策。 你應該與網域管理員合作,從網域層級套用程式碼完整性政策。

  1. 使用 New-AppLockerPolicy,為您要指定為受控安裝程式的檔案建立 EXE 規則。 這個範例是透過使用 Publisher 規則類型來建立 Hekaton DLL 產生器的規則,但你也可以使用任何 AppLocker 的規則類型。 您可能需要重新格式化輸出以取得可讀性。

    # Change the current working path of the PowerShell command line or ISE to
    # something other than the default (that is, C:\Temp). Retrieve SQL Server Path.
    $sqlPathParams = @{
       Path = 'HKLM:\SOFTWARE\Microsoft\MSSQLServer\Setup'
       Name = 'SQLPath'
    }
    $SQLPath = Get-ItemProperty @sqlPathParams
    
    $joinPathParams = @{
       Path = $SQLPath.SQLPath
       ChildPath = 'Binn\xtp'
    }
    $FullPath = Join-Path @joinPathParams
    
    # Set an environment variable for the In-memory OLTP Path.
    [System.Environment]::SetEnvironmentVariable('SQLPathWithXtp', $FullPath, 'Process')
    
    # Generate an AppLocker Policy for hkdllgen.exe in the current working directory.
    # The Get-AppLockerFileInformation cmdlet extracts the executable's publisher
    # information, and generates a hash for the binary.
    $hkDllGenPath = Join-Path -Path $env:SQLPathWithXtp -ChildPath 'hkdllgen.exe'
    
    $newPolicyParams = @{
       RuleType = 'Publisher'
       User = 'Everyone'
       Xml = $true
    }
    Get-ChildItem -Path $hkDllGenPath |
    Get-AppLockerFileInformation |
    New-AppLockerPolicy @newPolicyParams > AppLocker_HkDllGen_Policy.xml
    
  2. 手動編輯 AppLocker_HkDllGen_Policy.xml 並變更下列屬性值:

    • RuleCollection Type 到 ManagedInstaller
    • EnforcementMode 到 AuditOnly
    • BinaryVersionRange LowSection 到 "*" 和 HighSection 到 "*"

    改變:

    <RuleCollection Type="Exe" EnforcementMode="NotConfigured">
    

    至:

    <RuleCollection Type="ManagedInstaller" EnforcementMode="AuditOnly">
    

    改變:

    <BinaryVersionRange LowSection="2022.160.4175.1" HighSection="2022.160.4175.1"/>
    

    至:

    <BinaryVersionRange LowSection="*" HighSection="*"/>
    
  3. 部署 AppLocker 受控安裝程式設定原則。 你可以匯入 AppLocker 原則並使用群組原則部署,或如以下 PowerShell 指令所示,使用指令碼搭配 Set-AppLockerPolicy 指令程式來部署該原則。

    #Enable the AppLocker Policy and merge with the existing policy that exists on the system.
    Set-AppLockerPolicy -XmlPolicy .\AppLocker_HkDllGen_Policy.xml -Merge -ErrorAction SilentlyContinue
    
  4. 如果你用 PowerShell 腳本部署 AppLocker 政策,請使用 appidtel.exe 管理命令提示字元的工具來設定 AppLocker 應用程式身份服務和 AppLocker 過濾驅動程式。

    appidtel.exe start [-mionly]
    

在商務用 Windows Defender 應用程控精靈中啟用受管理的安裝程序選項

為了讓Windows Defender應用程式控制(WDAC)信任程序hkdllgen.exe產生的 DLL,請在你的應用程式控制政策中指定啟用:管理安裝程式選項。 請使用 Set-RuleOption cmdlet 與選項 13 來定義此設定。

從其中一個 WDAC 基底原則精靈 範本基底原則產生程式代碼完整性原則檔案。

從 預設的 Windows 原則開始,這本指南會移除一些選項,使剩下的選項更少。 欲了解更多關於預設 Windows 模式與允許 Microsoft 模式政策的資訊,請參閱「企業基礎政策範例應用程式控制」文章。

基底範本原則

WDAC 基底範本畫面的螢幕快照。

選擇 Windows 政策基礎範本後,命名該政策並選擇將 App Control 政策儲存在磁碟的位置。

選取原則類型

選擇多重政策格式與基礎政策作為政策類型。

WDAC 選取原則類型畫面的螢幕快照。

設定原則範本

僅啟用 受管理安裝程式、 無需重啟的更新政策、 未簽署系統完整性政策,以及 使用者模式程式碼完整性 政策的規則選項。 停用其他原則規則選項。 要更改設定,請選擇政策規則標題旁的滑桿按鈕。

下表說明每條政策規則,從最左邊的欄位開始。 政策規則文章提供了每條政策規則的更詳細描述。

規則選項 描述
受管理的安裝程式 使用此選項可自動允許由軟體發行解決方案(如定義為受管理安裝程式的 Hekaton DLL 產生器)安裝的應用程式。
更新政策無需重新啟動 使用此選項可讓未來的商務應用程控原則更新套用,而不需要重新啟動系統。
未簽署的系統完整性原則 允許政策保持未簽署。 當此選項被移除時,必須簽署該政策,並將 UpdatePolicySigners 加入政策中,以啟用未來的政策修改。
使用者模式程式代碼完整性 商務用應用程控原則會限制內核模式和使用者模式二進位檔。 根據預設,只會限制內核模式二進位檔。 啟用此規則選項會驗證使用者模式可執行檔和腳稿。

[設定原則範本] 畫面的螢幕快照。

您應該一開始啟用 稽核模式,因為它可讓您在強制執行原則之前測試新的商務用應用程控原則。 使用稽核模式時,沒有任何應用程式會被封鎖。 相反地,當政策外的應用程式啟動時,該政策會記錄事件。 基於這個理由,所有範本預設都會啟用稽核模式。

檔案規則

從列表中移除所有政策簽署規則。

WDAC 檔案規則畫面的螢幕快照。

(可選)新增 hkdllgen.exe 的自訂發行者允許規則。 此規則利用執行檔現有 Microsoft 程式碼簽章憑證的資訊來識別並允許匹配的 HkDllGen 版本。

WDAC 自定義原則畫面的螢幕快照。

發行者檔案規則類型會使用程式碼簽署憑證鏈中的屬性來制定檔案規則。

WDAC 原則規則畫面的螢幕快照。

選擇 「建立規則」後,應該會有一個單一的政策簽署規則。

WDAC 原則簽署規則清單畫面的螢幕快照。

部署您的應用程式控制原則。 請參閱 部署企業應用程控原則。

建立政策後,新政策會寫入被選為政策檔案位置的路徑。 新的二進位版本的政策檔名會包含檔名末尾的政策版本。 你可以將檔案複製<policy>.cip到 C:\Windows\System32\CodeIntegrity\CiPolicies\Active SQL Server 實例的子目錄。

手動部署程式代碼完整性原則

為了建立更簡化的程式碼完整性政策,你可以編輯完成 WDAC 應用程式控制政策嚮導後產生的較通用 <policy>.xml 檔案。 如果你不是在 SQL Server 上執行 WDAC 應用程式控制政策向導,而是從工作站執行,這種情況就可能發生。 例如,較不自定義的程式代碼完整性原則檔案看起來可能像這樣:

<?xml version="1.0" encoding="utf-8"?>
<SiPolicy xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="urn:schemas-microsoft-com:sipolicy" PolicyType="Base Policy">
  <VersionEx>10.0.5.0</VersionEx>
  <PlatformID>{XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX}</PlatformID>
  <PolicyID>{XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX}</PolicyID>
  <BasePolicyID>{XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX}</BasePolicyID>
  <Rules>
    <Rule>
      <Option>Enabled:Unsigned System Integrity Policy</Option>
    </Rule>
    <Rule>
      <Option>Enabled:UMCI</Option>
    </Rule>
    <Rule>
      <Option>Enabled:Audit Mode</Option>
    </Rule>
    <Rule>
      <Option>Enabled:Managed Installer</Option>
    </Rule>
    <Rule>
      <Option>Enabled:Update Policy No Reboot</Option>
    </Rule>
  </Rules>
  <EKUs>
    <!--EKU ID-->
  </EKUs>
  <FileRules>
    <!--FileAttrib ID -->
  </FileRules>
  <Signers />
  <SigningScenarios>
    <SigningScenario ID="ID_SIGNINGSCENARIO_KMCI" FriendlyName="Kernel Mode Signing Scenario" Value="131">
      <ProductSigners />
    </SigningScenario>
    <SigningScenario ID="ID_SIGNINGSCENARIO_UMCI" FriendlyName="User Mode Signing Scenario" Value="12">
      <ProductSigners />
    </SigningScenario>
  </SigningScenarios>
  <UpdatePolicySigners />
  <HvciOptions>0</HvciOptions>
</SiPolicy>

此範例沒有簽署的發佈者規則,且假設政策檔使用本地工作目錄(例如 C:\Temp),檔名為 Hekaton_Custom_CIPolicy.xml。

$policyPath = 'C:\Temp\Hekaton_Custom_CIPolicy.xml'

# Create Windows Defender Application Control (WDAC)
# policy and set Option 13 (Enabled:Managed Installer)
# and Option 16 (Enabled:Update Policy No Reboot)
$policyIdParams = @{
    FilePath = $policyPath
    PolicyName = 'Hekaton Managed Installer Policy'
    ResetPolicyID = $true
}
Set-CIPolicyIdInfo @policyIdParams

$option13Params = @{
    FilePath = $policyPath
    Option = 13
}
Set-RuleOption @option13Params

$option16Params = @{
    FilePath = $policyPath
    Option = 16
}
Set-RuleOption @option16Params

# Retrieve the Policy ID from the App Control policy XML.
# Code Integrity uses this ID as the binary file name.
[xml]$AppControlPolicy = Get-Content -Path $policyPath
$PolicyID = $AppControlPolicy.SiPolicy.PolicyID
$PolicyBinary = $PolicyID + '.cip'

# Convert the App Control policy XML to binary format and
# save it into the Active Code Integrity path.
$convertParams = @{
    XmlFilePath = $policyPath
    BinaryFilePath = "C:\Windows\System32\CodeIntegrity\CiPolicies\Active\$PolicyBinary"
}
ConvertFrom-CIPolicy @convertParams

若要套用原則而不重新啟動伺服器並檢查程式代碼完整性的狀態,請執行此 PowerShell 腳本:

# Refresh the Code Integrity policy without a reboot of the system
$updateCiParams = @{
    Namespace  = 'root\Microsoft\Windows\CI'
    ClassName  = 'PS_UpdateAndCompareCIPolicy'
    MethodName = 'Update'
    Arguments  = @{ FilePath = "C:\Windows\System32\CodeIntegrity\CiPolicies\Active\$PolicyBinary" }
}
Invoke-CimMethod @updateCiParams

# View the current status of WDAC Code Integrity. If WDAC is in Audit mode
# the "UserModeCodeIntegrityPolicyEnforcementStatus" has a value of "1"
# for Audit mode. A value of "0" mean that Code Integrity is not active.
$deviceGuardParams = @{
    ClassName = 'Win32_DeviceGuard'
    Namespace = 'root\Microsoft\Windows\DeviceGuard'
}
Get-CimInstance @deviceGuardParams | Format-List *codeintegrity*

確認所產生的 Hekaton DLL 是否受到程式碼完整性的信任

在 AppLocker 管理安裝程式規則及所需 AppLocker 服務啟用後,透過 HkDllGen 產生新的 In-Memory OLTP DLL。 Windows 會追蹤 HkDllGen 程序樹,並為該程序樹建立的檔案新增$KERNEL.SMARTLOCKER.ORIGINCLAIM一個擴展屬性。

當 App Control 在啟用 Enabled:Managed Installer 的情況下以稽核或強制模式運作時,Code Integrity 可根據所產生 DLL 的受管理安裝程式來源來信任該 DLL。 為了驗證擴充屬性是否已加入,請從 \Data\xtp\<database_id> 資料夾中選擇一個新產生的 DLL,並從提升命令提示字元執行以下指令:

fsutil file queryea "D:\SQL\MSSQL17.MSSQLSERVER\MSSQL\DATA\xtp\5\xtp_t_5_64719283_196202718557591_1.dll"

fsutil 輸出的螢幕快照。

僅憑 $KERNEL.SMARTLOCKER.ORIGINCLAIM 的存在,並不能證明該檔案來自受管理的安裝程式。 同一擴展屬性可記錄智慧安全圖譜的來源及信任的繼承方式。 在第一個資料列中,在第二個 ULONG 的開頭,00 會識別受管理安裝程式的來源,而 01 會識別智慧型安全性圖表的來源。 欲評估剩餘的原產地權利要求值,請參閱 管理安裝程式與 ISG 技術參考。

拿掉受管理的安裝程式功能

要移除裝置上的受管安裝程式功能,請依照刪除 AppLocker 規則中的指示移除受管安裝程式 AppLocker 政策: 清除單一系統或遠端系統上的 AppLocker 政策。