Manipulando a representação do cliente em drivers UMDF

Este tópico descreve como um driver um User-Mode Driver Framework (UMDF) acessa recursos protegidos, começando na UMDF versão 2.

Os drivers UMDF normalmente são executados na conta LocalService e não podem acessar arquivos ou recursos que exigem credenciais de usuário, como arquivos protegidos ou outros recursos protegidos. Um driver UMDF normalmente opera em comandos e dados que fluem entre um aplicativo cliente e um dispositivo. Portanto, a maioria dos drivers UMDF não acessa recursos protegidos.

No entanto, alguns drivers podem exigir acesso a um recurso protegido. Por exemplo, um driver UMDF pode carregar firmware em um dispositivo de um arquivo que um aplicativo cliente fornece. O arquivo pode ter uma ACL (lista de controle de acesso) que impede que usuários não autorizados modifiquem o arquivo e controlem o dispositivo. Infelizmente, essa ACL também impede que o driver UMDF acesse o arquivo.

A estrutura fornece uma funcionalidade de representação que permite que os drivers representem o cliente do driver e obtenham os direitos de acesso do cliente aos recursos protegidos.

Habilitando a representação

O pacote de instalação do driver UMDF e o aplicativo cliente devem habilitar a funcionalidade de representação da estrutura, da seguinte maneira:

  • O arquivo INF do pacote de instalação do driver UMDF deve incluir a diretiva UmdfImpersonationLevel e definir o nível máximo de representação permitido. A representação só será habilitada se o arquivo INF incluir a diretiva UmdfImpersonationLevel . Para obter mais informações sobre como definir o nível de representação, consulte Especificando diretivas WDF em arquivos INF.

  • O aplicativo cliente deve definir o nível de representação permitido para cada identificador de arquivo. O aplicativo usa as configurações de QoS (qualidade de serviço) na função CreateFile do Microsoft Win32 para definir o nível de representação permitido. Para obter mais informações sobre essas configurações, consulte o parâmetro dwFlagsAndAttributes de CreateFile na documentação do SDK do Windows.

Manipulando representação para uma solicitação de E/S

O driver UMDF e a estrutura manipulam a representação de uma solicitação de E/S na seguinte sequência:

  1. O driver chama o método WdfRequestImpersonate para especificar o nível de representação necessário e uma função de retorno de chamada EvtRequestImpersonate .

  2. A estrutura verifica o nível de representação solicitado. Se o nível solicitado for maior que o nível que o pacote de instalação do driver UMDF e o aplicativo cliente permitirem, a solicitação de representação falhará. Caso contrário, a estrutura representará o cliente e chamará imediatamente a função de retorno de chamada EvtRequestImpersonate .

A função de retorno de chamada EvtRequestImpersonate deve executar apenas as operações que exigem o nível de representação solicitado, como abrir um arquivo protegido.

A estrutura não permite que a função de retorno de chamada EvtRequestImpersonate de um driver chame nenhum dos métodos de objeto da estrutura. Isso garante que o driver não exponha o nível de representação a outras funções de retorno de chamada de driver ou outros drivers.

Como prática recomendada, seu driver não deve habilitar o cancelamento de uma solicitação de E/S antes de chamar WdfRequestImpersonate para essa solicitação.

O método WdfRequestImpersonate concede apenas o nível de representação que o driver solicita.

Passando credenciais para baixo na pilha do driver

Quando o driver recebe uma solicitação de E/S do tipo WdfRequestTypeCreate, o driver pode encaminhar a solicitação de E/S para baixo na pilha do driver para um driver no modo kernel. Os drivers no modo kernel não têm a capacidade de representação que o WdfRequestImpersonate fornece aos drivers UMDF.

Portanto, se você quiser que um driver no modo kernel receba as credenciais de usuário do cliente (em vez das credenciais do processo de host do driver), o driver deverá definir o sinalizador WDF_REQUEST_SEND_OPTION_IMPERSONATE_CLIENT quando chamar WdfRequestSend para enviar a solicitação de criação para o destino de E/S. O método Send retornará um código de erro se a tentativa de representação falhar, a menos que o driver também defina o sinalizador WDF_REQUEST_SEND_OPTION_IMPERSONATION_IGNORE_FAILURE .

O exemplo a seguir mostra como um driver UMDF pode usar o sinalizador WDF_REQUEST_SEND_OPTION_IMPERSONATE_CLIENT para enviar uma solicitação de criação de arquivo para um destino de E/S. O arquivo INF do driver também deve incluir a diretiva UmdfImpersonationLevel , conforme descrito acima.

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);
}

O driver não precisa chamar WdfRequestImpersonate antes de enviar a solicitação para o destino de E/S.

Se os drivers de nível inferior também encaminharem a solicitação, o nível de representação do cliente percorrerá a pilha do driver.

Reduzindo ameaças à segurança

Para reduzir a chance de um ataque de "elevação de privilégio", você deve:

  • Tente evitar o uso de representação.

    Por exemplo, para evitar usar a representação para abrir um arquivo que o driver deve usar, o aplicativo cliente pode abrir o arquivo e usar operações de E/S para enviar conteúdo de arquivo para o driver.

  • Use o nível de representação mais baixo exigido pelo driver.

    Defina o nível de representação no arquivo INF do driver o mais baixo possível. Se o driver não exigir nenhuma representação, não inclua a diretiva UmdfImpersonationLevel no arquivo INF.

  • Minimize as oportunidades para um invasor explorar seu driver.

    Sua função de retorno de chamada EvtRequestImpersonate deve conter uma pequena seção de código que executa apenas a operação que requer representação. Por exemplo, se o driver acessar um arquivo protegido, ele exigirá representação somente quando ele abrir o identificador de arquivo. Ele não requer representação para ler ou gravar no arquivo.