次の方法で共有


イベントを安全に受信する

一時および永続コンシューマーには、イベント配信をセキュリティで保護するさまざまな方法があります。

以下のセクションでは、次に示すトピックについて説明します。

一時コンシューマーのセキュリティ保護

"一時コンシューマー" は、システムが再起動されるか、WMI が停止するまで実行されますが、特定のイベントが発生した場合は開始されません。 たとえば、SWbemServices.ExecNotificationQueryAsync を呼び出すと、一時コンシューマーが作成されます。

SWbemServices.ExecNotificationQuery または IWbemServices::ExecNotificationQuery を呼び出すと、一時イベント コンシューマーが作成されます。 一時コンシューマーでは、作成されるイベント "シンク" にイベントを提供するユーザーを制御できません。

ExecNotificationQuery メソッドは、同期的、半同期的、または非同期的に呼び出すことができます。 たとえば、SWbemServices.ExecNotificationQuery は、iflags パラメーターの設定方法に応じて半同期的に呼び出すことができる同期メソッドです。 SWbemServices.ExecNotificationQueryAsync は非同期的に呼び出されます。

これらの呼び出しの非同期バージョンのシンクへのコールバックは、スクリプトによる呼び出しと同じ認証レベルで返されない可能性があることに注意してください。 そのため、非同期呼び出しの代わりに半同期を使用することをお勧めします。 非同期通信が必要な場合は、メソッドの呼び出しに関する記事および「非同期呼び出しでのセキュリティの設定」を参照してください。

スクリプト サブスクライバーは、スクリプトによって作成されたシンクにイベントを提供するためにイベント プロバイダーのアクセス権をチェックすることはできません。 そのため、SWbemServices.ExecNotificationQuery の呼び出しでは、特定のセキュリティ設定で半同期形式の呼び出しを使用することをお勧めします。 詳細については、「VBScript を使用して半同期呼び出しを行う」を参照してください。

永続コンシューマーのセキュリティ保護

"永続コンシューマー" には、オペレーティング システムの再起動後に保持されるイベント プロバイダーからのイベントに対する永続的なサブスクリプションがあります。 永続コンシューマーをサポートするイベント プロバイダーは、"イベント コンシューマー プロバイダー" となります。 イベントが発生したときにイベント プロバイダーが実行されていない場合、WMI はイベントを配信する必要があるときにプロバイダーを起動します。 WMI はどのコンシューマー プロバイダーにイベントが配信されるかを、コンシューマー プロバイダー __Win32Provider インスタンスを、コンシューマー プロバイダーが定義した "論理コンシューマー クラス" に関連付ける __EventConsumerProviderRegistration インスタンスに基づいて、特定します。 コンシューマー プロバイダーのロールの詳細については、「イベント コンシューマー プロバイダーの作成」を参照してください。

永続コンシューマーは、イベントを送信するユーザーを制御でき、イベント プロバイダーは自分のイベントにアクセスするユーザーを制御できます。

クライアント スクリプトとアプリケーションでは、サブスクリプションの一部として論理コンシューマー クラスのインスタンスを作成します。 論理コンシューマー クラスでは、イベントに含まれる情報、クライアントがイベントを使用して実行できる操作、およびイベントの配信方法を定義します。

WMI 標準コンシューマー クラス には、論理コンシューマー クラスのロールの例が用意されています。 詳細については、「標準コンシューマーを使用したイベントの監視と対応」を参照してください。

永続的なサブスクリプションのセキュリティ保護

永続的なサブスクリプションでは、WMI でセキュリティに関する問題が発生する可能性が高いため、次のセキュリティ要件が設定されています。

  • 論理コンシューマー インスタンスである __EventFilter、および __FilterToConsumerBinding インスタンスでは、CreatorSID プロパティにある個別のセキュリティ ID (SID) が同じ必要があります。 詳細については、永続的なサブスクリプションのすべてのインスタンスで同じ SID を保持する方法に関するセクションを参照してください。

  • サブスクリプションを作成するアカウントは、ローカル管理者特権を持つドメイン アカウントか、ローカル管理者グループのアカウントである必要があります。 管理者グループの SID を使用すると、ネットワークから切断されている場合でも、サブスクリプションをローカル コンピューターで引き続き動作させることができます。 ドメイン アカウントを使用すると、ユーザーを正確に識別できます。

    ただし、コンピューターが接続されておらず、作成中のアカウントがドメイン アカウントである場合、WMI はアカウントの ID を確認できないため、コンシューマーは失敗します。 コンピューターがネットワークから切断された場合のサブスクリプション エラーを回避するには、管理者グループの SID をサブスクリプションに使用します。 この場合は、LocalSystem アカウントがドメイン上のグループ メンバーシップ データにアクセスできることを確認する必要があります。 一部のイベント コンシューマー プロバイダーでは、不正なサブスクリプションが大きな損害を引き起こす可能性があるため、特に高いセキュリティ要件が設定されています。 標準コンシューマーである ActiveScriptEventConsumerCommandLineEventConsumer がその例です。

  • 永続的なサブスクリプションは、特定のイベント プロバイダー ID からのイベントのみを受け入れるように構成できます。 __EventFilter インスタンスの EventAccess プロパティのセキュリティ記述子をイベント プロバイダー ID に設定します。 WMI は、イベント プロバイダーの ID をセキュリティ記述子と比較して、プロバイダーが WBEM_RIGHT_PUBLISH アクセス許可を持っているかどうかを判断します。 詳しくは、「WMI セキュリティ定数」をご覧ください。

    フィルターでイベント プロバイダー ID へのアクセスが許可されている場合は、イベントも信頼されます。 これにより、イベントを受信したコンシューマーは、委任されたイベントを発生できます。

    EventAccess のセキュリティ記述子の既定値は NULL で、すべてのユーザーにアクセスできます。 イベント セキュリティを強化するために、__EventFilter のサブスクリプション インスタンスでのアクセスを制限することをお勧めします。

管理者専用 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")

イベント プロバイダー ID の偽装

永続コンシューマーは、イベントを処理するためにイベント プロバイダーを偽装する必要がある場合があります。 永続コンシューマーは、次の条件が満たされている場合にのみイベント プロバイダーを偽装できます。

  • __FilterToConsumerBinding のインスタンスで、MaintainSecurityContext プロパティが True に設定されている。
  • イベントが、プロバイダーがイベントを生成したときと同じセキュリティ コンテキストで配信されている。 インプロセス コンシューマーである DLL として実装されたコンシューマーのみが、プロバイダーのセキュリティ コンテキストでイベントを受信できます。 インプロセス プロバイダーとコンシューマーのセキュリティについて詳しくは、「プロバイダーのホスティングとセキュリティ」を参照してください。
  • イベント プロバイダーが、偽装できるプロセスで実行されている。

コンシューマー プロセスを実行しているアカウントは、WMI リポジトリ (CIM リポジトリとも呼ばれます) に対する FULL_WRITE アクセス許可を持っている必要があります。 サブスクリプションでは、__FilterToConsumerBinding__EventConsumer、および __EventFilter インスタンスの CreatorSID プロパティにある個別のセキュリティ ID (SID) 値が同じ必要があります。 WMI では、各インスタンスの CreatorSID に SID が格納されます。

SID と永続的なサブスクリプション

バインド、コンシューマー、フィルターが同じユーザーによって作成されていない場合、永続的なサブスクリプションは機能しません。つまり、__FilterToConsumerBinding__EventConsumer、および __EventFilter は、CreatorSID プロパティにある個別のセキュリティ ID (SID) 値が同じ必要があります。 Windows Management Instrumentation (WMI) には、この値が格納されます。

ドメイン アカウントを使用した永続的なサブスクリプションの作成

ドメイン アカウントを使用して永続的なサブスクリプションを作成する場合は、いくつかの問題を考慮する必要があります。 永続的なサブスクリプションは、ユーザーがログオンしていない場合でも機能し続ける必要があります。つまり、組み込みの LocalSystem アカウントで機能します。

ドメイン ユーザーがセキュリティに影響するコンシューマー (ActiveScriptEventConsumerCommandLineEventConsumer) の永続的なサブスクリプションの作成者である場合、WMI は、__EventFilter クラス、__FilterToConsumerBinding クラス、コンシューマー インスタンスの CreatorSID プロパティがローカル管理者グループのメンバーであるユーザーに属しているかどうかを確認します。

次のコード例は、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 イベントの受信