Partilhar via


Modelo de segurança do Windows para desenvolvedores de drivers

O modelo de segurança do Windows é baseado em objetos protegíveis. Cada componente do sistema operacional deve garantir a segurança dos objetos pelos quais é responsável. Os condutores devem, por conseguinte, salvaguardar a segurança dos seus dispositivos e objetos.

Este tópico resume como o modelo de segurança do Windows se aplica aos drivers de modo kernel.

Modelo de segurança do Windows

O modelo de segurança do Windows é baseado principalmente em direitos por objeto, com um pequeno número de privilégios em todo o sistema. Os objetos que podem ser protegidos incluem, mas não estão limitados a, processos, threads, eventos e outros objetos de sincronização, bem como arquivos, diretórios e dispositivos.

Para cada tipo de objeto, os direitos genéricos de leitura, gravação e execução são mapeados em direitos específicos de objeto detalhados. Por exemplo, para arquivos e diretórios, os direitos possíveis incluem o direito de ler ou gravar o arquivo ou diretório, o direito de ler ou gravar atributos de arquivo estendidos, o direito de atravessar um diretório e o direito de escrever o descritor de segurança de um objeto.

O modelo de segurança envolve os seguintes conceitos:

  • Identificadores de segurança (SIDs)
  • Tokens de acesso
  • Descritores de segurança
  • Listas de controle de acesso (ACLs)
  • Privilégios

Identificadores de segurança (SIDs)

Um identificador de segurança (SID, também chamado deprincipal de ) identifica um usuário, um grupo ou uma sessão de logon. Cada usuário tem um SID exclusivo, que é recuperado pelo sistema operacional no logon.

Os SIDs são emitidos por uma autoridade, como o sistema operacional ou um servidor de domínio. Alguns SIDs são bem conhecidos e têm nomes e identificadores. Por exemplo, o SID S-1-1-0 identifica Todos (ou Mundo).

Tokens de acesso

Cada processo tem um token de acesso. O token de acesso descreve o contexto de segurança completo do processo. Ele contém o SID do usuário, o SID dos grupos aos quais o usuário pertence e o SID da sessão de logon, bem como uma lista dos privilégios de todo o sistema concedidos ao usuário.

Por padrão, o sistema usa o token de acesso primário para um processo sempre que um thread do processo interage com um objeto protegível. No entanto, um thread pode representar uma conta de cliente. Quando um thread é representado, ele tem um token de representação, além de seu próprio token principal. O token de representação descreve o contexto de segurança da conta de usuário que o thread está representando. A impersonação é especialmente comum no tratamento de Chamada de Procedimento Remoto (RPC).

Um token de acesso que descreve um contexto de segurança restrito para um thread ou processo é chamado de token restrito. Os SIDs em um token restrito podem ser definidos apenas para negar acesso, não para permitir acesso, a objetos protegíveis. Além disso, o token pode descrever um conjunto limitado de privilégios em todo o sistema. O SID e a identidade do usuário permanecem os mesmos, mas os direitos de acesso do usuário são limitados enquanto o processo está usando o token restrito. A função CreateRestrictedToken cria um token restrito.

Descritores de segurança

Cada objeto Windows nomeado tem um descritor de segurança; alguns objetos sem nome também. O descritor de segurança descreve os SIDs de proprietário e grupo para o objeto, juntamente com suas ACLs.

O descritor de segurança de um objeto geralmente é criado pela função que cria o objeto. Quando um driver chama o IoCreateDevice ou rotina de IoCreateDeviceSecure para criar um objeto de dispositivo, o sistema aplica um descritor de segurança ao objeto de dispositivo criado e define ACLs para o objeto. Para a maioria dos dispositivos, as ACLs são especificadas no arquivo de informações do dispositivo (INF).

Para obter mais informações os Descritores de Segurança na documentação do driver do kernel.

Listas de Controle de Acesso

As ACLs (Listas de Controle de Acesso) permitem um controle refinado sobre o acesso a objetos. Uma ACL faz parte do descritor de segurança para cada objeto.

Cada ACL contém zero ou mais Entradas de Controle de Acesso (ACE). Cada ACE, por sua vez, contém um único SID que identifica um usuário, grupo ou computador e uma lista de direitos que são negados ou permitidos para esse SID.

ACLs para objetos de dispositivo

A ACL de um objeto de dispositivo pode ser definida de três maneiras:

  • Defina o descritor de segurança padrão para seu tipo de dispositivo.
  • Criado programaticamente pela função RtlCreateSecurityDescriptor e definido pela função RtlSetDaclSecurityDescriptor.
  • Especificado em Security Descriptor Definition Language (SDDL) no ficheiro INF do dispositivo ou numa chamada para a rotina IoCreateDeviceSecure.

Todos os drivers devem usar SDDL no arquivo INF para especificar ACLs para seus objetos de dispositivo.

SDDL é uma linguagem de descrição extensível que permite que os componentes criem ACLs em um formato de cadeia de caracteres. SDDL é usado tanto pelo modo de usuário quanto pelo código de modo kernel. A figura a seguir mostra o formato das cadeias de caracteres SDDL para objetos de dispositivo.

Diagrama mostrando o formato de cadeias de caracteres SDDL para objetos de dispositivo.

O valor Access especifica o tipo de acesso permitido. O valor SID especifica um identificador de segurança que determina a quem o valor Access se aplica (por exemplo, um usuário ou grupo).

Por exemplo, a seguinte string SDDL permite que o System (SY) acesse tudo e permita que todos os outros (WD) só tenham acesso de leitura:

“D:P(A;;GA;;;SY)(A;;GR;;;WD)”

O arquivo de cabeçalho wdmsec.h também inclui um conjunto de cadeias de caracteres SDDL predefinidas que são adequadas para objetos de dispositivo. Por exemplo, o arquivo de cabeçalho define SDDL_DEVOBJ_SYS_ALL_ADM_RWX_WORLD_RWX_RES_RWX da seguinte maneira:

"D:P(A;;GA;;;SY)(A;;GRGWGX;;;BA)(A;;GRGWGX;;;WD)(A;;GRGWGX;;;RC)"

O primeiro segmento desta string permite que o kernel e o sistema operacional (SY) tenham controle completo sobre o dispositivo. O segundo segmento permite que qualquer pessoa no grupo Administradores (BA) integrado acesse todo o dispositivo, mas não altere a ACL. O terceiro segmento permite que todos (WD) leiam ou gravem no dispositivo, e o quarto segmento concede os mesmos direitos ao código não confiável (RC). Os drivers podem usar as cadeias de caracteres predefinidas como estão ou como modelos para cadeias de caracteres específicas do objeto do dispositivo.

Todos os objetos de dispositivo em uma pilha devem ter as mesmas ACLs. Alterar as ACLs num objeto de dispositivo na pilha altera as ACLs em toda a pilha de dispositivos.

No entanto, adicionar um novo objeto de dispositivo à pilha não altera nenhuma ACL, seja a do novo objeto de dispositivo (se ele tiver ACLs) ou a de qualquer objeto de dispositivo existente na pilha. Quando um driver cria um novo objeto de dispositivo e o anexa ao topo da pilha, o driver deve copiar as ACLs da pilha para o novo objeto de dispositivo copiando o campo DeviceObject.Characteristics do driver imediatamente inferior.

A rotina de IoCreateDeviceSecure oferece suporte a um subconjunto de cadeias de caracteres SDDL que usam SIDs predefinidos, como WD e SY. APIs de modo de usuário e arquivos INF suportam a sintaxe SDDL completa.

Verificações de segurança usando ACLs

Quando um processo solicita acesso a um objeto, as verificações de segurança comparam as ACLs do objeto com os SIDs no token de acesso do chamador.

O sistema compara as ACEs em uma ordem estrita de cima para baixo e para na primeira partida relevante. Portanto, ao criar uma ACL, você deve sempre colocar as ACEs de negação acima das ACEs de concessão correspondentes. Os exemplos a seguir mostram como a comparação prossegue.

Exemplo 1: Comparando uma ACL com um token de acesso

O Exemplo 1 mostra como o sistema compara uma ACL com o token de acesso para o processo de um chamador. Suponha que o chamador deseja abrir um arquivo que tem a ACL que é mostrada na tabela a seguir.

Exemplo de ficheiro ACL

Permissão SID Acesso
Permitir Contabilidade Gravar, excluir
Permitir Vendas Anexar
Negar Avisos legais Acrescentar, escrever, eliminar
Permitir Todos Ler

Esta ACL possui quatro ACEs, que se aplicam especificamente aos grupos de Contabilidade, Vendas, Jurídico e Geral.

Em seguida, suponha que o token de acesso para o processo de solicitação contém SIDs para um usuário e três grupos, na seguinte ordem:

Usuário Jim (S-1-5-21...)

Contabilidade de Grupo (S-1-5-22...)

Grupo Jurídico (S-1-5-23...)

Grupo Todos (S-1-1-0)

Ao comparar uma ACL de arquivo com um token de acesso, o sistema primeiro procura uma ACE para o usuário Jim na ACL do arquivo. Nenhum aparece, então em seguida ele procura um ACE para o grupo Contabilidade. Como mostrado na tabela anterior, uma ACE para o grupo Contabilidade aparece como a primeira entrada na ACL do arquivo, portanto, o processo de Jim recebe o direito de gravar ou excluir o arquivo e a comparação é interrompida. Se, em vez disso, a ACE do grupo Legal precedesse a ACE do grupo Contabilidade na ACL, seria negado ao processo o acesso de gravação, acréscimo e exclusão ao arquivo.

Exemplo 2: Comparando uma ACL com um token restrito

O sistema compara uma ACL a um token restrito da mesma forma que compara aqueles em um token que não é restrito. No entanto, um SID de negação num token restrito pode corresponder apenas a um ACE de negação numa ACL.

O Exemplo 2 mostra como o sistema compara a ACL de um arquivo com um token restrito. Suponha que o arquivo tenha a mesma ACL mostrada na tabela anterior. Neste exemplo, no entanto, o processo tem um token restrito que contém os seguintes SIDs:

Usuário Jim (S-1-5-21...) Negar

Contabilidade de Grupo (S-1-5-22...) Negar

Grupo Jurídico (S-1-5-23...) Negar

Grupo Todos (S-1-1-0)

A ACL do arquivo não lista o SID de Jim, portanto, o sistema prossegue para o SID do grupo de Contabilidade. Embora a ACL do ficheiro tenha uma ACE para o grupo de Contabilidade, esta ACE permite o acesso; por isso, não corresponde ao SID no token restrito do processo, que nega o acesso. Como resultado, o sistema avança para o SID do grupo legal. A ACL do arquivo contém uma ACE para o grupo Legal que nega acesso, assim, o processo não pode gravar, anexar ou excluir o arquivo.

Privilégios

Um privilégio é o direito de um usuário executar uma operação relacionada ao sistema no computador local, como carregar um driver, alterar a hora ou desligar o sistema.

Os privilégios são diferentes dos direitos de acesso porque se aplicam a tarefas e recursos relacionados ao sistema em vez de objetos, e porque são atribuídos a um usuário ou grupo por um administrador de sistema, em vez de pelo sistema operacional.

O token de acesso para cada processo contém uma lista dos privilégios concedidos ao processo. Os privilégios devem ser habilitados especificamente antes do uso. Para obter mais informações sobre privilégios, consulte Privilégios na documentação do controlador do núcleo.

A extensão !acl formata e exibe o conteúdo de uma lista de controle de acesso (ACL). Para obter mais informações, consulte Determinando a ACL de um objeto e !acl.

A extensão !token exibe uma exibição formatada de um objeto de token de segurança. Para obter mais informações, consulte !token.

A extensão !tokenfields exibe os nomes e deslocamentos dos campos dentro do objeto de token de acesso (a estrutura TOKEN). Para obter mais informações, consulte ! tokenfields.

A extensão !sid exibe o identificador de segurança (SID) no endereço especificado. Para obter mais informações, consulte !sid.

A extensão !sd exibe o descritor de segurança no endereço especificado. Para obter mais informações, consulte !sd.

Cenário do modelo de segurança do Windows: Criando um arquivo

O sistema usa as construções de segurança descritas no modelo de segurança do Windows sempre que um processo cria um identificador para um arquivo ou objeto.

O diagrama a seguir mostra as ações relacionadas à segurança que são acionadas quando um processo de modo de usuário tenta criar um arquivo.

Fluxograma que ilustra as ações relacionadas à segurança quando um processo de modo de usuário tenta criar um arquivo.

O diagrama anterior mostra como o sistema responde quando um aplicativo de modo de usuário chama a função CreateFile. As seguintes notas referem-se aos números circulares na figura:

  1. Um aplicativo de modo de usuário chama a função CreateFile, passando um nome de arquivo válido do Microsoft Win32.
  2. O modo de usuário Kernel32.dll passa a solicitação para Ntdll.dll, que converte o nome Win32 para um nome de arquivo do Microsoft Windows NT.
  3. Ntdll.dll chama a função NtCreateFile com o nome de arquivo do Windows. Dentro Ntoskrnl.exe, o Gerenciador de E/S lida com NtCreateFile.
  4. O Gerenciador de E/S reempacota a solicitação em uma chamada do Gerenciador de Objetos.
  5. O Gerenciador de Objetos resolve links simbólicos e garante que o usuário tenha direitos de travessia para o caminho no qual o arquivo será criado. Para obter mais informações, consulte Verificações de segurança no Gerenciador de objetos.
  6. O Gerenciador de Objetos chama o componente do sistema que possui o tipo de objeto subjacente associado à solicitação. Para uma solicitação de criação de arquivo, esse componente é o Gerenciador de E/S, que possui objetos de dispositivo.
  7. O Gerenciador de E/S verifica o descritor de segurança do objeto do dispositivo em relação ao token de acesso do processo do usuário para garantir que o usuário tenha o acesso necessário ao dispositivo. Para obter mais informações, consulte Verificações de segurança no Gerenciador de E/S.
  8. Se o processo do usuário tiver o acesso necessário, o Gerenciador de E/S criará um identificador e enviará uma solicitação de IRP_MJ_CREATE ao driver do dispositivo ou sistema de arquivos.
  9. O driver executa verificações de segurança adicionais, conforme necessário. Por exemplo, se a solicitação especificar um objeto no namespace do dispositivo, o driver deverá garantir que o chamador tenha os direitos de acesso necessários. Para obter mais informações, consulte Verificações de segurança no driver.

Verificações de segurança no Gerenciador de Objetos

A responsabilidade pela verificação dos direitos de acesso pertence ao componente de nível mais alto que pode realizar tais verificações. Se o Object Manager puder verificar os direitos de acesso do chamador, ele fará isso. Caso contrário, o Gerenciador de objetos passa a solicitação para o componente responsável pelo tipo de objeto subjacente. Esse componente, por sua vez, verifica o acesso, se possível; se não puder, ele passa a solicitação para um componente ainda mais baixo, como um driver.

O Gerenciador de Objetos verifica as ACLs em busca de tipos de objeto simples, como eventos e bloqueios mutex. Para objetos que têm um namespace, o proprietário do tipo executa verificações de segurança. Por exemplo, o Gestor de E/S é considerado o responsável pelo tipo para objetos de dispositivo e objetos de arquivo. Se o Gerenciador de Objetos encontrar o nome de um objeto de dispositivo ou objeto de arquivo ao analisar um nome, ele transfere o nome para o Gerenciador de E/S, como no cenário de criação de arquivo apresentado acima. Em seguida, o Gerenciador de E/S verifica os direitos de acesso, se possível. Se o nome especificar um objeto dentro de um namespace de dispositivo, o Gerenciador de E/S, por sua vez, transfere o nome para o driver do dispositivo (ou sistema de arquivos) e esse driver é responsável por validar o acesso solicitado.

Verificações de segurança no Gerenciador de E/S

Quando o Gerenciador de E/S cria um identificador, ele verifica os direitos do objeto em relação ao token de acesso ao processo e, em seguida, armazena os direitos concedidos ao usuário junto com o identificador. Quando solicitações de E/S posteriores chegam, o Gerenciador de E/S verifica os direitos associados ao identificador para garantir que o processo tenha o direito de executar a operação de E/S solicitada. Por exemplo, se o processo solicitar posteriormente uma operação de gravação, o Gerenciador de E/S verificará os direitos associados ao identificador para garantir que o chamador tenha acesso de gravação ao objeto.

Caso o identificador seja duplicado, é possível remover direitos da cópia, mas não adicioná-los.

Quando o Gerenciador de E/S cria um objeto, ele converte modos de acesso Win32 genéricos em direitos específicos do objeto. Por exemplo, os seguintes direitos se aplicam a arquivos e diretórios:

Modo de acesso Win32 Direitos específicos do objeto
ACESSO_GENÉRICO_LEITURA LerDados
ESCRITA_GENÉRICA EscreverDados
EXECUÇÃO_GENÉRICA ReadAttributes
GENERIC_ALL Tudo

Para criar um ficheiro, um processo deve ter permissões de atravessamento para os diretórios pais no caminho de destino. Por exemplo, para criar \Device\CDROM0\Directory\File.txt, um processo deve ter o direito de atravessar \Device, \Device\CDROM0 e \Device\CDROM0\Directory. O Gestor de E/S verifica apenas os direitos de percurso desses diretórios.

O Gestor de E/S verifica os direitos de percurso quando analisa o nome do ficheiro. Se o nome do arquivo for um link simbólico, o Gerenciador de E/S o resolverá para um caminho completo e, em seguida, verificará os direitos de travessia, começando pela raiz. Por exemplo, suponha que o link simbólico \DosDevices\D mapeia para o nome do dispositivo Windows NT \Device\CDROM0. O processo deve ter permissões de acesso para atravessar o diretório \Device.

Para obter mais informações, consulte Object Handles e Object Security.

Verificações de segurança no motorista

O kernel do sistema operacional trata cada driver, na verdade, como um sistema de arquivos com seu próprio namespace. Consequentemente, quando um chamador tenta criar um objeto no namespace do dispositivo, o Gerenciador de E/S verifica se o processo tem direitos de passagem para os diretórios no caminho.

Com drivers WDM, o Gerenciador de E/S não executa verificações de segurança no namespace, a menos que o objeto de dispositivo tenha sido criado especificando FILE_DEVICE_SECURE_OPEN. Quando FILE_DEVICE_SECURE_OPEN não está definido, o driver é responsável por garantir a segurança de seu namespace. Para obter mais informações, consulte Controlando o acesso ao namespace do dispositivo e Protegendo objetos de dispositivo.

Para os drivers WDF, o sinalizador FILE_DEVICE_SECURE_OPEN está sempre ativado para que o descritor de segurança do dispositivo seja verificado antes de permitir que uma aplicação aceda a quaisquer nomes no namespace do dispositivo. Para obter mais informações, consulte Controlando o acesso a dispositivos em drivers KMDF.

Limites de segurança do Windows

Os motoristas que se comunicam entre si e com chamadores de modo de usuário de diferentes níveis de privilégio podem ser considerados como ultrapassando um limite de confiança. Um limite de confiança é qualquer caminho de execução de código que passa de um processo com privilégios inferiores para um processo com privilégios mais elevados.

Quanto maior a disparidade nos níveis de privilégio, mais interessante é a fronteira para os atacantes que desejam executar ataques, como um ataque de escalação de privilégios contra o driver ou processo visado.

Parte do processo de criação de um modelo de ameaça é examinar os limites de segurança e procurar caminhos imprevistos. Para obter mais informações, consulte Modelagem de ameaças para controladores.

Todos os dados que cruzam um limite de confiança não são confiáveis e devem ser validados.

Este diagrama mostra três drivers de kernel e dois aplicativos, um em um contêiner de aplicativo e um aplicativo que é executado com direitos de administrador. As linhas vermelhas indicam limites de confiança de exemplo.

Diagrama que descreve a superfície de ataque do driver com três drivers do kernel, um aplicativo em um contêiner de aplicativo e um aplicativo com direitos de administrador.

Como o contêiner de aplicativo pode fornecer restrições adicionais e não está sendo executado em nível de administrador, o caminho (1) é um caminho de maior risco para um ataque de escalonamento, uma vez que o limite de confiança é entre um contêiner de aplicativo (um processo de privilégio muito baixo) e um driver de kernel.

O caminho (2) é um caminho de menor risco, pois o aplicativo está sendo executado com direitos de administrador e está chamando diretamente para o driver do kernel. O nível administrativo já é um privilégio bastante alto no sistema, por isso a superfície de ataque do nível administrativo para o kernel é menos um alvo interessante para os invasores, mas ainda assim um limite de confiança digno de nota.

O caminho (3) é um exemplo de um caminho de execução de código que cruza vários limites de confiança que podem ser perdidos se um modelo de ameaça não for criado. Neste exemplo, há um limite de confiança entre o driver 1 e o driver 3, pois o driver 1 recebe a entrada do aplicativo de modo de usuário e a passa diretamente para o driver 3.

Todas as entradas que entram no driver a partir do modo de usuário não são confiáveis e devem ser validadas. As entradas provenientes de outros condutores também podem não ser fidedignas, dependendo se o condutor anterior foi apenas uma simples passagem (por exemplo, os dados foram recebidos pelo condutor 1 a partir da aplicação 1, o condutor 1 não fez qualquer validação nos dados e apenas os transmitiu ao condutor 3). Certifique-se de identificar todas as superfícies de ataque e limites de confiança e validar todos os dados que os cruzam, criando um modelo de ameaça completo.

Recomendações do modelo de segurança do Windows

  • Defina ACLs padrão fortes em chamadas para a rotina IoCreateDeviceSecure.
  • Especifique ACLs no arquivo INF para cada dispositivo. Essas ACLs podem afrouxar ACLs padrão apertadas, se necessário.
  • Defina a característica FILE_DEVICE_SECURE_OPEN para aplicar as configurações de segurança do objeto do dispositivo ao namespace do dispositivo.
  • Não defina IOCTLs que permitam FILE_ANY_ACCESS a menos que esse acesso não possa ser explorado maliciosamente.
  • Utilize a rotina IoValidateDeviceIoControlAccess para reforçar a segurança nos IOCTLS existentes que permitem FILE_ANY_ACCESS.
  • Crie um modelo de ameaça para examinar os limites de segurança e procurar caminhos imprevistos. Para obter mais informações, consulte Modelação de ameaças para drivers.
  • Consulte lista de verificação de segurança do condutor para obter recomendações adicionais para a segurança do condutor.

Ver também

Protegendo objetos do dispositivo

Lista de verificação de segurança do condutor