安全地接收事件

暫時和永久消費者有不同的確保事件傳遞的方法。

本主題將討論下列各節:

保護暫時取用者

暫存取用者 執行,直到系統重新啟動或WMI停止,但如果引發特定事件,則無法啟動。 例如,呼叫 SWbemServices.ExecNotificationQueryAsync 會建立暫時取用者。

SWbemServices.ExecNotificationQuery 或 IWbemServices::ExecNotificationQuery 建立暫時性事件使用者。 暫時性使用者無法控制誰將事件輸送至他們建立的事件接收器 。

ExecNotificationQuery 方法的呼叫可以同步、半同步或異步進行。 例如,SWbemServices.ExecNotificationQuery 是一種同步方法,根據 iflags 參數的設定方式,可以半同步地呼叫。 SWbemServices.ExecNotificationQueryAsync 是異步呼叫。

請注意,針對這些呼叫之異步版本,回呼至接收端的可能不會以與腳本所發起呼叫相同的驗證層級傳回。 因此,建議您使用半同步,而不是非同步呼叫。 如果您需要非同步通訊,請參閱 呼叫一個方法 和 設定非同步呼叫的安全性。

腳本訂閱者無法檢查事件提供者的訪問權限,無法確認事件是否能送至由腳本建立的接收器。 因此,建議呼叫 SWbemServices.ExecNotificationQuery 使用呼叫的半同步形式,並使用特定的安全性設定。 如需詳細資訊,請參閱使用 VBScript 進行半同步呼叫 。

保護永久取用者

永久取用者 具有事件提供者的永久訂閱,即使作業系統重新啟動後也會維持。 支援永久使用者的事件提供者是 事件使用者提供者。 如果事件發生時事件提供者未執行,則 WMI 會在需要傳遞事件時啟動提供者。 WMI 會根據 __EventConsumerProviderRegistration 實例來識別應傳遞事件的取用者提供者,該實例會將取用者提供者 __Win32Provider 實例與取用者提供者所定義的 邏輯取用者類別產生關聯。 如需關於消費者提供者角色的更多資訊,請參閱 撰寫事件消費者提供者。

永久取用者可以控制傳送事件的人員,而事件提供者可以控制誰存取其事件。

用戶端腳本和應用程式會在訂閱中建立邏輯使用者類別的實例。 邏輯取用者類別會定義事件所包含的資訊、用戶端如何處理事件,以及傳遞事件的方式。

WMI 標準取用者類別 提供邏輯取用者類別角色的範例。 如需詳細資訊,請參閱 使用標準取用者監視和回應事件。

保護永久訂閱

永久訂用帳戶在 WMI 中造成安全性問題的可能性更大,因此具有下列安全性需求:

  • 邏輯取用者實例、__EventFilter和 __FilterToConsumerBinding 實例在 CreatorSID 屬性中必須有相同的個別安全性標識碼 (SID)。 如需詳細資訊,請參閱 在永久訂閱的所有實例中保留相同的 SID。

  • 建立訂用帳戶的帳戶必須是具有本地系統管理員權限的網域帳戶,或是本地 Administrators 群組帳戶。 使用 Administrators 群組 SID 可以讓訂閱服務在本機電腦上持續運作,即使與網路中斷連線也是如此。 使用網域帳戶可精確識別使用者。

    不過,如果計算機未連線且建立帳戶是網域帳戶,取用者會失敗,因為 WMI 無法驗證帳戶的身分識別。 若要避免電腦斷開網路時發生訂閱失敗,請使用 Administrators 群組的 SID 來進行訂閱。 在此情況下,您應該確定 LocalSystem 帳戶可以存取網域上的群組成員資格數據。 某些事件消費者提供者的安全性需求特別高,因為惡意訂閱可能會造成重大損害。 範例包括標準取用者、ActiveScriptEventConsumer 和 CommandLineEventConsumer。

  • 您可以將永久訂用帳戶設定為只接受來自特定事件提供者身分識別的事件。 將 __EventFilter 實例 EventAccess 屬性中的安全性描述元設定為事件提供者身分識別。 WMI 會將事件提供者的身分識別與安全性描述元進行比較,以判斷提供者是否具有 WBEM_RIGHT_PUBLISH 存取權。 如需詳細資訊,請參閱 WMI 安全性常數。

    如果篩選允許存取事件提供者身分識別,則它也會信任事件。 這允許接收事件的消費者引發一個委派的事件。

    附註EventAccess 中安全描述子的預設值是 NULL,允許所有人存取。 建議限制 __EventFilter 訂用帳戶實例中的存取權,以提升事件安全性。

設定 Administrator-Only SD

下列C++程式代碼範例會在 __EventFilter 實例上建立僅限系統管理員的安全性描述元。 此範例會使用 安全性描述元定義語言 (SDDL) 建立安全性描述元。 如需 WBEM_RIGHT_SUBSCRIBE的詳細資訊,請參閱 WMI 安全性常數。

// Create SD that allows only administrators 
//    to send events to this filter. 
// The SDDL settings are O:BAG:BAD:(A;;0x80;;;BA)
// Set the EventAccess property in the 
//    IWbemClassObject of the __EventFilter instance. 
   long lMask = WBEM_RIGHT_PUBLISH;
     WCHAR wBuf[MAX_PATH];
     _ltow( lMask, wBuf, 16 );
 
HRESULT hRes = pEventFilterInstance->Put( L"EventAccess", 0,
    &_variant_t( L"O:BAG:BAD:(A;;0x80;;;BA)" ), NULL );

上述程式代碼範例需要下列參考和 #include 語句。

#define _WIN32_DCOM
#include <wbemidl.h>
#include <comdef.h>

#pragma comment(lib, "wbemuuid.lib")

模擬事件提供者身份識別

永久消費者可能需要假扮事件提供者來處理事件。 永久性消費者只能在下列條件存在時模仿事件提供者:

  • __FilterToConsumerBinding 的實例 MaintainSecurityContext 屬性設定為 True。
  • 事件會在提供者產生事件時所在的相同安全性內容中傳遞。 只有被實作為 DLL 的消費者,即在同一進程中運行的消費者,才能在提供者的安全性上下文中接收事件。 如需瞭解進程中提供者與消費者安全性的更多資訊,請參閱 提供者裝載和安全性。
  • 事件提供者正在執行允許仿真的進程中。

執行使用者程式的帳戶必須對 WMI 存放庫(也稱為 CIM 存放庫)具有 FULL_WRITE 的存取權。 在訂用帳戶中,__FilterToConsumerBinding、__EventConsumer和 __EventFilter 實例在 CreatorSID 屬性中必須有相同的個別安全性標識碼 (SID) 值。 WMI 會將 SID 儲存在每個實例的 CreatorSID 中。

SID 和永久訂閱

系結、取用者和篩選不是由同一位使用者建立時,永久訂閱無法運作,這表示 __FilterToConsumerBinding、__EventConsumer和 __EventFilter 在 CreatorSID 屬性中必須具有相同的個別安全性標識符 (SID) 值。 Windows Management Instrumentation (WMI) 會儲存此值。

使用網域帳戶建立永久訂閱

使用網域帳戶建立永久訂閱時,必須考慮幾個問題。 當沒有任何使用者登入時,每個永久訂用帳戶仍應運作,這表示它們會在內建 LocalSystem 帳戶下運作。

如果網域使用者是安全性敏感性取用者永久訂用帳戶的建立者(ActiveScriptEventConsumer、CommandLineEventConsumer),則 WMI 會驗證 __EventFilter 類別的 CreatorSID 屬性、__FilterToConsumerBinding 類別,以及取用者實例是否屬於屬於本機 Administrators 群組成員的使用者。

下列程式代碼範例示範如何指定 CreatorSID 屬性。

 instance of __EventFilter as $FILTER
    {
        // this is the Administrators SID in array of bytes format
        CreatorSID = {1,2,0,0,0,0,0,5,32,0,0,0,32,2,0,0};    
        // Add filter code here ...
    }

    instance of ActiveScriptEventConsumer as $CONSUMER
    {
       CreatorSID = {1,2,0,0,0,0,0,5,32,0,0,0,32,2,0,0};
       // Add consumer code here ...
    }

    instance of __FilterToConsumerBinding
    {
       CreatorSID = {1,2,0,0,0,0,0,5,32,0,0,0,32,2,0,0};
       Consumer = $CONSUMER;
       Filter = $FILTER;
       // Add binding code here ...
    }

針對跨網域情況,將已驗證的使用者新增至「Windows 授權存取群組」。

保護 WMI 事件

接收 WMI 事件