UMDF ドライバーでのクライアント偽装の処理

このトピックでは、UMDF バージョン 2 以降、ユーザー モード ドライバー フレームワーク (UMDF) ドライバーが保護されたリソースにアクセスする方法について説明します。

UMDF ドライバーは通常、LocalService アカウントで実行され、保護されたファイルやその他の保護されたリソースなど、ユーザーの資格情報を必要とするファイルやリソースにはアクセスできません。 UMDF ドライバーは通常、クライアント アプリケーションとデバイスの間を流れるコマンドとデータに対して動作します。 そのため、ほとんどの UMDF ドライバーは、保護されたリソースにアクセスしません。

ただし、一部のドライバーでは、保護されたリソースへのアクセスが必要になる場合があります。 たとえば、UMDF ドライバーは、クライアント アプリケーションが提供するファイルからデバイスにファームウェアをロードする可能性があります。 このファイルには、権限のないユーザーがファイルを変更したり、デバイスを制御したりするのを防ぐアクセス制御リスト (ACL) が含まれている場合があります。 残念ながら、この ACL を使用すると、UMDF ドライバーがファイルにアクセスすることもできなくなります。

フレームワークは、ドライバーがドライバーのクライアントを偽装し、保護されたリソースに対するクライアントのアクセス権を取得できるようにする偽装機能を提供します。

権限借用の有効化

次のように、UMDF ドライバーのインストール パッケージとクライアント アプリケーションの両方は、フレームワークの偽装機能を有効にする必要があります:

  • UMDF ドライバーのインストール パッケージの INF ファイルには、 UmdfImpersonationLevelディレクティブを含め、許可される最大偽装レベルを設定する必要があります。 偽装は、INF ファイルに UmdfImpersonationLevel ディレクティブが含まれている場合にのみ有効になります。 偽装レベルの設定の詳細については、Specifying WDF Directives in INF Filesをご参照ください。

  • クライアント アプリケーションは、ファイル ハンドルごとに許可される偽装レベルを設定する必要があります。 アプリケーションは、 Microsoft Win32 CreateFile関数のサービス品質 (QoS) 設定を使用して、許可される偽装レベルを設定します。 これらの設定の詳細については、Windows SDK ドキュメンテイションの CreateFiledwFlagsAndAttributesパラメーターをご参照ください。

I/O リクエストのの偽装の処理

UMDF ドライバーとフレームワークは、次のシーケンスで I/O リクエストの偽装を処理します:

  1. ドライバーは、WdfRequestImpersonateメソッドを呼び出して、必要な偽装レベルとEvtRequestImpersonateコールバック関数を指定します。

  2. フレームワークは、要求された偽装レベルをチェックします。 要求されたレベルが、UMDF ドライバーのインストール パッケージとクライアント アプリケーションで許可されているレベルより大きい場合、偽装リクエストは失敗します。 それ以外の場合、フレームワークはクライアントを偽装し、すぐにEvtRequestImpersonateコールバック関数を呼び出します。

EvtRequestImpersonateコールバック関数は、保護されたファイルを開くなど、要求された偽装レベルを必要とする操作のみを実行しなければなりません。

フレームワークは、ドライバーのEvtRequestImpersonateコールバック関数がフレームワークのオブジェクト メソッドのいずれかを呼び出すことを許可しません。 これにより、ドライバーが偽装レベルを他のドライバーコールバック関数や他のドライバーに公開しないようにします。

ベスト プラクティスとして、ドライバーは、WdfRequestImpersonateをそのリクエストに対して呼び出す前に、I/O リクエストのキャンセルを有効にすべきではありません。

WdfRequestImpersonateメソッドは、ドライバーが要求する偽装レベルのみを許可します。

ドライバー スタックに資格情報を渡します

ドライバーがWdfRequestTypeCreateタイプの I/O リクエストを受信した場合、ドライバーは I/O リクエストをドライバー スタックからカーネル モード ドライバーに転送する可能性があります。 カーネル モード ドライバーには、WdfRequestImpersonateがUMDF ドライバーに提供する偽装機能はありません。

そのため、カーネル モード ドライバーがクライアントのユーザー資格情報 (driver host processの資格情報ではなく) を受け取りたい場合、ドライバーはWdfRequestSendを呼び出して作成リクエストを I/O ターゲットに送信するときに、WDF_REQUEST_SEND_OPTION_IMPERSONATE_CLIENTフラグを設定する必要があります。 ドライバーもWDF_REQUEST_SEND_OPTION_IMPERSONATION_IGNORE_FAILURE フラグを設定しない限り、偽装の試行が失敗した場合、Send メソッドはエラー コードを返します。

次の例は、UMDF ドライバーが WDF_REQUEST_SEND_OPTION_IMPERSONATE_CLIENTフラグを使用して I/O ターゲットにファイル作成リクエストを送信する方法を示しています。 ドライバーの INF ファイルには、前述のようにUmdfImpersonationLevelディレクティブも含める必要があります。

WDFIOTARGET iotarget;
WDF_REQUEST_SEND_OPTIONS options;
NTSTATUS status;
WDF_REQUEST_PARAMETERS params;
ULONG sendFlags;  
 
WDF_REQUEST_PARAMETERS_INIT(&params);
WdfRequestGetParameters(Request, &params);
   
sendFlags = WDF_REQUEST_SEND_OPTION_SYNCHRONOUS;
if (params.Type == WdfRequestTypeCreate) {
    sendFlags |= WDF_REQUEST_SEND_OPTION_IMPERSONATE_CLIENT;
}
   
WDF_REQUEST_SEND_OPTIONS_INIT(&options, sendFlags);
if (WdfRequestSend(Request,
                   iotarget,
                   &options
                   ) == FALSE) {
    status = WdfRequestGetStatus(Request);
}

ドライバーは、I/O ターゲットにリクエストを送信する前に WdfRequestImpersonateを呼び出す必要はありません。

下位レベルのドライバーもリクエストを転送すると、クライアントの偽装レベルがドライバー スタックの下に移動します。

セキュリティ上の脅威の軽減

「特権の昇格」攻撃の可能性を減らすには、次の手順を実行する必要があります:

  • 偽装の使用を避けるようにしてください。

    たとえば、偽装を使用してドライバーが使わなければならないファイルを開くのを避けるために、クライアント アプリケーションはファイルを開き、I/O 操作を使用してファイルの内容をドライバーに送信できます。

  • ドライバーに必要な最も低い偽装レベルを使用します。

    ドライバーの INF ファイルの偽装レベルをできるだけ低く設定します。 ドライバーが偽装を必要としない場合は、INF ファイルにUmdfImpersonationLevelディレクティブを含めないでください。

  • 攻撃者がドライバーを悪用する機会を最小限に抑えます。

    EvtRequestImpersonateコールバック関数には、偽装を必要とする操作のみを実行する小さなコードセクションを含める必要があります。 たとえば、ドライバーが保護されたファイルにアクセスする場合は、ファイル ハンドルを開くときにのみ偽装が必要です。 ファイルの読み取りまたは書き込みに偽装は必要ありません。