Обработка олицетворения клиента в драйверах UMDF

В этом разделе описывается, как драйвер User-Mode Driver Framework (UMDF) обращается к защищенным ресурсам, начиная с UMDF версии 2.

Драйверы UMDF обычно выполняются под учетной записью LocalService и не могут получить доступ к файлам или ресурсам, которым требуются учетные данные пользователя, например к защищенным файлам или другим защищенным ресурсам. Драйвер UMDF обычно работает с командами и данными, которые передаются между клиентским приложением и устройством. Поэтому большинство драйверов UMDF не обращаются к защищенным ресурсам.

Однако некоторым драйверам может потребоваться доступ к защищенному ресурсу. Например, драйвер UMDF может загружать встроенное ПО на устройство из файла, который предоставляет клиентское приложение. Файл может содержать список управления доступом (ACL), который не позволяет неавторизованным пользователям изменять файл и управлять устройством. К сожалению, этот список управления доступом также не позволяет драйверу UMDF получить доступ к файлу.

Платформа предоставляет возможность олицетворения, которая позволяет драйверам олицетворять клиент драйвера и получать права доступа клиента к защищенным ресурсам.

Включение олицетворения

Как пакет установки драйвера UMDF, так и клиентское приложение должны включить возможность олицетворения платформы следующим образом:

  • INF-файл пакета установки драйвера UMDF должен содержать директиву UmdfImpersonationLevel и задавать максимально допустимый уровень олицетворения. Олицетворение включено, только если INF-файл содержит директиву UmdfImpersonationLevel . Дополнительные сведения о настройке уровня олицетворения см. в разделе Указание директив WDF в INF-файлах.

  • Клиентское приложение должно задать допустимый уровень олицетворения для каждого дескриптора файла. Приложение использует параметры качества обслуживания (QoS) в функции Microsoft Win32 CreateFile , чтобы задать допустимый уровень олицетворения. Дополнительные сведения об этих параметрах см. в параметре dwFlagsAndAttributescreateFile в документации windows SDK.

Обработка олицетворения для запроса ввода-вывода

Драйвер UMDF и платформа обрабатывают олицетворение для запроса ввода-вывода в следующей последовательности:

  1. Драйвер вызывает метод WdfRequestImpersonate , чтобы указать необходимый уровень олицетворения и функцию обратного вызова EvtRequestImpersonate .

  2. Платформа проверяет запрошенный уровень олицетворения. Если запрошенный уровень превышает уровень, разрешенный пакетом установки драйвера UMDF и клиентским приложением, запрос олицетворения завершается ошибкой. В противном случае платформа олицетворяет клиента и немедленно вызывает функцию обратного вызова EvtRequestImpersonate .

Функция обратного вызова EvtRequestImpersonate должна выполнять только операции, требующие запрошенного уровня олицетворения, например открытие защищенного файла.

Платформа не позволяет функции обратного вызова EvtRequestImpersonate драйвера вызывать какие-либо объектные методы платформы. Это гарантирует, что драйвер не будет предоставлять уровень олицетворения другим функциям обратного вызова драйвера или другим драйверам.

Рекомендуется, чтобы драйвер не разрешал отмену запроса ввода-вывода перед вызовом WdfRequestImpersonate для этого запроса.

Метод WdfRequestImpersonate предоставляет только уровень олицетворения, запрашиваемый драйвером.

Передача учетных данных в стеке драйверов

Когда драйвер получает типизированный запрос ввода-вывода WdfRequestTypeCreate, драйвер может перенаправить запрос ввода-вывода в стек драйвера в режиме ядра. Драйверы в режиме ядра не имеют возможности олицетворения, которые WdfRequestImpersonate предоставляет драйверам UMDF.

Поэтому, если требуется, чтобы драйвер в режиме ядра получал учетные данные пользователя клиента (а не учетные данные хост-процесса драйвера), драйвер должен установить флаг WDF_REQUEST_SEND_OPTION_IMPERSONATE_CLIENT при вызове WdfRequestSend , чтобы отправить запрос на создание целевому объекту ввода-вывода. Метод Send возвращает код ошибки, если попытка олицетворения завершается неудачно, если драйвер также не устанавливает флаг WDF_REQUEST_SEND_OPTION_IMPERSONATION_IGNORE_FAILURE .

В следующем примере показано, как драйвер UMDF может использовать флаг WDF_REQUEST_SEND_OPTION_IMPERSONATE_CLIENT для отправки запроса на создание файла целевому объекту ввода-вывода. 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);
}

Драйверу не нужно вызывать WdfRequestImpersonate перед отправкой запроса в целевой объект ввода-вывода.

Если драйверы нижнего уровня также перенаправят запрос, уровень олицетворения клиента перемещается вниз по стеку драйверов.

Снижение угроз безопасности

Чтобы снизить вероятность атаки с повышением привилегий, необходимо:

  • Старайтесь не использовать олицетворение.

    Например, чтобы избежать использования олицетворения для открытия файла, который должен использовать драйвер, клиентское приложение может открыть файл и использовать операции ввода-вывода для отправки содержимого файла в драйвер.

  • Используйте самый низкий уровень олицетворения, необходимый драйверу.

    Установите уровень олицетворения в INF-файле драйвера как можно ниже. Если драйвер не требует олицетворения, не включайте директиву UmdfImpersonationLevel в INF-файл.

  • Сведите к минимуму возможности злоумышленника использовать ваш драйвер.

    Функция обратного вызова EvtRequestImpersonate должна содержать небольшой раздел кода, который выполняет только операцию, требующую олицетворения. Например, если драйвер обращается к защищенному файлу, он требует олицетворения только при открытии дескриптора файла. Для чтения из файла или записи в него не требуется олицетворение.