Compartilhar via


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

Neste artigo, você encontra uma lista de verificação de segurança de driver para desenvolvedores que desejam reduzir o risco de comprometimento dos drivers. A segurança do driver é crítica e afeta diretamente a confiabilidade. Quando o Windows detectar que o acesso à memória incorreto está ocorrendo, ele desligará o sistema operacional e exibirá uma tela de erro azul. Como um parceiro do Windows, você deve trabalhar para reduzir o impacto significativo que um driver com falha tem na vida de nossos clientes.

Para obter mais informações sobre os benefícios de fornecer um driver seguro e confiável, consulte Diretrizes de segurança do driver.

Visão geral da segurança do driver

Uma falha de segurança é qualquer falha que permita que um invasor cause um mau funcionamento de um driver de modo que ele permita que um invasor obtenha acesso não autorizado, manipule o sistema ou comprometa dados, potencialmente fazendo com que o sistema falhe ou se torne inutilizável. Além disso, vulnerabilidades no código do driver podem permitir que um invasor obtenha acesso ao kernel, possibilitando o comprometimento de todo o sistema operacional.

O objetivo da maioria dos desenvolvedores que trabalham com drivers é fazer com que o driver funcione corretamente, e não se haverá um invasor mal-intencionado tentando explorar vulnerabilidades em seu código. Entretanto, depois que um driver é lançado, os invasores podem tentar investigar e identificar falhas de segurança. Os desenvolvedores devem pensar nesses problemas durante a fase de design e implementação para minimizar a probabilidade dessas vulnerabilidades. O objetivo é eliminar todas as falhas de segurança conhecidas antes que o driver seja lançado.

A criação de drivers mais seguros exige cooperação do arquiteto do sistema (que pensa cuidadosamente nas possíveis ameaças ao driver), do desenvolvedor que implementa o código (que codifica defensivamente operações comuns que podem ser a causa das explorações) e da equipe de teste (que tenta proativamente encontrar pontos fracos e vulnerabilidades). Com a coordenação adequada de todas essas atividades, a segurança do driver aumenta drasticamente.

Além de evitar os problemas associados a um driver que está sendo alvo de ataque, muitas das etapas descritas, como o uso mais preciso da memória do kernel, aumentarão a confiabilidade do driver. Isso reduz os custos de suporte e aumenta a satisfação do cliente com seu produto. Realizar as tarefas da lista de verificação abaixo pode ajudar você a atingir todos esses objetivos.

Lista de verificação de segurança:Conclua a tarefa de segurança descrita em cada um desses tópicos.

Caixa de seleção desmarcada que representa um item na lista de verificação de segurança. Confirme se há necessidade de um driver de kernel

Caixa de seleção desmarcada que representa um item na lista de verificação de segurança. Use as estruturas do driver

Caixa de seleção desmarcada que representa um item na lista de verificação de segurança.Gerencie o controle de acesso do driver

Caixa de seleção desmarcada que representa um item na lista de verificação de segurança.Controle o acesso a drivers que são somente de software

Caixa de seleção desmarcada que representa um item na lista de verificação de segurança. Siga as diretrizes de codificação segura do driver

Caixa de seleção não marcada que representa um item na lista de verificação de segurança.Implementar código compatível com HVCI

Caixa de seleção desmarcada que representa um item na lista de verificação de segurança. Siga as práticas recomendadas de código específicas da tecnologia

Caixa de seleção desmarcada que representa um item na lista de verificação de segurança.Adicione anotações SAL ao código do driver

Caixa de seleção desmarcada que representa um item na lista de verificação de segurança.Faça revisão de código por pares

Caixa de seleção desmarcada que representa um item na lista de verificação de segurança.Faça uma análise de ameaças

Caixa de seleção desmarcada que representa um item na lista de verificação de segurança. Use o CodeQL para verificar o código do driver

Caixa de seleção desmarcada que representa um item na lista de verificação de segurança. Use o Driver Verifier para verificar vulnerabilidades

Caixa de seleção desmarcada que representa um item na lista de verificação de segurança.Verifique o código com os testes do programa de compatibilidade de hardware

Caixa de seleção desmarcada que representa um item na lista de verificação de segurança. Verifique os drivers prontos para envio com ferramentas como BinSkim e SignTool

Caixa de seleção desmarcada que representa um item na lista de verificação de segurança.Não assine o código do driver de teste em produção

Caixa de seleção desmarcada que representa um item na lista de verificação de segurança. Execute a assinatura corretamente do driver de lançamento e distribua seu pacote de driver usando o Windows Update

Caixa de seleção desmarcada que representa um item na lista de verificação de segurança. Use o Microsoft Vulnerable and Malicious Driver Reporting Center para saber como os drivers são reportados

Caixa de seleção desmarcada que representa um item na lista de verificação de segurança. Examine os recursos de codificação segura

Caixa de seleção desmarcada que representa um item na lista de verificação de segurança. Leia o Resumo das principais conclusões

Confirme se há necessidade de um driver de kernel

Item 1 da lista de verificação de segurança:Confirme se um driver de kernel é necessário e que uma abordagem de menor risco, como o serviço ou aplicativo do Windows, não é uma opção melhor.

Os drivers kernel residem no kernel do Windows e ter um problema ao executar no kernel expõe todo o sistema operacional. Se houver qualquer outra opção disponível, provavelmente será de menor custo e terá menos riscos associados do que criar um novo driver de kernel.

Para obter mais informações sobre como usar os drivers internos do Windows, consulte Você precisa escrever um driver?.

Para obter informações sobre como usar tarefas em segundo plano, consulte Como dar suporte ao aplicativo com tarefas em segundo plano.

Para obter informações sobre como usar os serviços do Windows, consulte Serviços.

Use as estruturas do driver

Item 2 da lista de verificação de segurança:Use as estruturas do driver para reduzir o tamanho do código e aumentar a confiabilidade e a segurança dele.

Use o Windows Driver Frameworks para reduzir o tamanho do seu código e aumentar sua confiabilidade e segurança. Para começar, leia Como usar o WDF para desenvolver um driver. Para obter informações sobre como usar o UMDF (User Mode Driver Framework) de menor risco, consulte Escolhendo um modelo de driver.

Gravar um driver antigo do WDM (Windows Driver Model) leva mais tempo, é caro e quase sempre envolve recriar o código disponível nas estruturas do driver.

O código-fonte do WDF (Windows Driver Framework) é de software livre e está disponível no GitHub. Esse é o mesmo código-fonte do WDF que é fornecido no Windows. Você pode depurar seu driver de forma mais eficaz quando puder acompanhar as interações entre o driver e o WDF. Para baixá-lo, acesse https://github.com/Microsoft/Windows-Driver-Frameworks.

DMF – Estrutura do Módulo de Driver

Considere o uso do DMF (Driver Module Framework) em seu projeto de driver. Desenvolvido pela equipe do Microsoft Surface, o DMF é uma estrutura que permite a criação de objetos WDF chamados módulos DMF. O código desses módulos DMF pode ser compartilhado entre drivers diferentes. Além disso, o DMF fornece uma biblioteca de módulos DMF que foram desenvolvidos para drivers e oferecem reutilização de código para tarefas como o gerenciamento de threads e E/S. Um módulo DMF é usado para encapsular tarefas de driver em unidades menores. Cada módulo é independente e tem seu próprio código, contexto e callbacks, facilitando a reutilização. Para obter mais informações, consulte Introdução ao Driver Module Framework e a documentação do site do GitHub .

Gerenciar o controle de acesso do motorista

Item de lista de verificação de segurança nº 3:Revise seu driver para verificar se você está controlando corretamente o acesso.

Como gerenciar o controle de acesso do driver – WDF

A função dos drivers é impedir que os usuários acessem indevidamente os dispositivos e arquivos de um computador. Para impedir o acesso não autorizado a dispositivos e arquivos, você deve:

  • Nomear objetos de dispositivo somente quando necessário. Os objetos de dispositivo nomeados geralmente são necessários apenas por motivos herdados. Por exemplo, se você tiver um aplicativo que espera abrir o dispositivo usando um nome específico ou se estiver usando um dispositivo não PNP/dispositivo de controle. Os drivers WDF não precisam nomear seu dispositivo PnP FDO para criar um link simbólico usando WdfDeviceCreateSymbolicLink.

  • Proteger o acesso a objetos e interfaces do dispositivo.

Para permitir que aplicativos ou outros drivers WDF acessem o PDO do dispositivo PnP, você deve usar interfaces de dispositivo. Para obter mais informações, consulte Usando Interfaces de Dispositivo. Uma interface de dispositivo serve como um link simbólico para o PDO da pilha de dispositivos.

Uma das melhores maneiras de controlar o acesso ao PDO é especificando uma cadeia de caracteres SDDL em seu INF. Se a cadeia de caracteres SDDL não estiver no arquivo INF, o Windows aplicará um descritor de segurança padrão. Para obter mais informações, consulte Proteção de objetos de dispositivos e SDDL para objetos de dispositivos.

Para obter mais informações sobre como controlar o acesso, consulte o seguinte:

Controlar o acesso ao dispositivo em drivers KMDF

Nomes, descritores de segurança e classes de dispositivo - Como tornar os objetos de dispositivo acessíveis... e SAFE do The NT Insider Newsletter de janeiro de fevereiro de 2017, publicado pela OSR.

Como gerenciar o controle de acesso do driver – WDM

Se você estiver trabalhando com um Driver WDM e tiver usado um objeto de dispositivo nomeado, poderá usar IoCreateDeviceSecure e especificar um SDDL para protegê-lo. Ao implementar IoCreateDeviceSecure, sempre especifique um GUID de classe personalizado para DeviceClassGuid. Você não deve especificar um GUID de classe existente aqui. Fazer isso pode interromper as configurações de segurança ou compatibilidade de outros dispositivos pertencentes a essa classe. Para obter mais informações, consulte WdmlibIoCreateDeviceSecure.

Para obter mais informações, consulte o seguinte:

Controlar o acesso ao dispositivo

Controlar o acesso ao namespace do dispositivo

Modelo de segurança do Windows para desenvolvedores de drivers

Hierarquia de risco de SIDs (identificadores de segurança)

A seção a seguir descreve a hierarquia de risco dos SIDs comuns usados no código do driver. Para obter informações gerais sobre SDDL, consulte SDDL para objetos de dispositivo, Cadeias de caracteres SID e Sintaxe de cadeia de caracteres SDDL.

É importante entender que, se os chamadores com privilégios inferiores tiverem permissão para acessar o kernel, o risco associado ao código será aumentado. Neste diagrama resumido, o risco aumenta à medida que você permite que SIDs de privilégios mais baixos acessem as funcionalidades do driver.

SY (System)
     \/
BA (Built-in Administrators)
     \/
LS (Local Service)
     \/
BU (Built-in User)
     \/
AC (Application Container)

Seguindo o princípio geral de segurança de privilégios mínimos, configure apenas o nível mínimo de acesso necessário para que o driver funcione.

Controle de segurança IOCTL granular do WDM

Um IOCTL (controle de entrada/saída) no Windows é uma chamada do sistema para operações de entrada/saída específicas do dispositivo. IOCTLs são usados por aplicativos para se comunicar com drivers de dispositivo, permitindo que eles enviem comandos ou solicitem informações do hardware. Para obter mais informações, consulte Introdução aos códigos de controle de E/S e solicitação de E/S de exemplo – uma visão geral.

Para gerenciar melhor a segurança quando IOCTLs são enviados por chamadores no modo de usuário, o código do driver pode incluir a função IoValidateDeviceIoControlAccess. Essa função permite que um driver verifique os direitos de acesso. Ao receber um IOCTL, um driver pode chamar IoValidateDeviceIoControlAccess, especificando FILE_READ_ACCESS, FILE_WRITE_ACCESS, ou ambos.

A implementação do controle de segurança IOCTL granular não substitui a necessidade de gerenciar o acesso do driver usando as técnicas abordadas anteriormente.

Para obter mais informações, consulte Definindo códigos de controle de E/S e Questões de segurança para códigos de controle de E/S.

Controle o acesso a drivers que são somente de software

Item 4 da lista de verificação de segurança:se um driver somente de software for criado, o controle de acesso adicional deverá ser implementado.

Os drivers de kernel baseados somente em software não usam plug-and-play (PnP) para se associar a identificações de hardware específicas e podem ser executados em qualquer computador. Esse driver pode ser usado para outros fins, criando um vetor de ataque.

Como os drivers de kernel que consistem apenas em software contêm riscos adicionais, sua execução deve ser restrita a hardware específico (por exemplo, usando um ID PnP exclusivo para permitir a criação de um driver PnP ou verificando a tabela SMBIOS para a presença de hardware específico).

Por exemplo, imagine que o OEM Fabrikam queira distribuir um driver que habilite um utilitário de overclock para seus sistemas. Se esse driver composto apenas de software for executado em um sistema de um OEM diferente, poderá ocorrer instabilidade ou dano ao sistema. Os sistemas da Fabrikam devem incluir uma ID PnP exclusiva para permitir a criação de um driver PnP que também possa ser atualizado por meio do Windows Update. Se isso não for possível, e a Fabrikam criar um driver Herdado, esse driver deverá encontrar outro método para verificar se ele está sendo executado em um sistema Fabrikam (por exemplo, examinando a tabela SMBIOS antes de habilitar quaisquer recursos).

Siga as diretrizes de codificação segura do driver

Item de lista de verificação de segurança nº 5:Examinar seu código e remover quaisquer vulnerabilidades de código conhecidas.

A atividade principal da criação de drivers seguros é identificar no código áreas que precisam ser alteradas para evitar vulnerabilidades de software conhecidas. Muitas dessas vulnerabilidades de software conhecidas envolvem o acompanhamento rigoroso do uso da memória para evitar problemas com outras partes que substituem ou comprometem as áreas de memória usadas pelo driver.

Ferramentas de varredura de código, como CodeQL e testes específicos de driver, podem ser usadas para ajudar a localizar algumas dessas vulnerabilidades (mas não todas). Essas ferramentas e testes são descritos posteriormente neste tópico.

Buffers de memória

Use o método apropriado para acessar buffers de dados com IOCTLs

Uma das principais responsabilidades de um driver do Windows é transferir dados entre aplicativos no modo de usuário e os dispositivos de um sistema. Os três métodos para acessar buffers de dados são mostrados na tabela a seguir.

Tipo de buffer IOCTL Resumo Para obter mais informações
METHOD_BUFFERED Recomendado para a maioria das situações Usar E/S em buffer
METHOD_IN_DIRECT ou METHOD_OUT_DIRECT Usado em algumas operações de entrada/saída de hardware de alta velocidade Usar E/S direta
METHOD_NEITHER Se possível, evite Não usar E/S direta nem em buffer

Em geral, a E/S em buffer é recomendada, pois fornece os métodos de buffer mais seguros. Mas mesmo ao usar E/S em buffer, existem riscos, como ponteiros inseridos, que devem ser atenuados.

Para obter mais informações sobre como trabalhar com buffers em IOCTLs, consulte Métodos para acessar buffers de dados.

Erros no uso de E/S bufferizada do IOCTL

  • Verifique o tamanho dos buffers relacionados a IOCTL. Para obter mais informações, consulte Falha ao verificar o tamanho dos buffers.

  • Inicialize corretamente os buffers de saída. Para obter mais informações, consulte Falha ao inicializar buffers de saída.

  • Valide corretamente os buffers de comprimento variável. Para obter mais informações, consulte Falha ao validar buffers de comprimento variável.

  • Ao usar E/S em buffer, certifique-se de retornar o comprimento correto para o OutputBuffer no campo Informações da estrutura IO_STATUS_BLOCK. Não retorne diretamente o comprimento de uma solicitação READ. Por exemplo, pense em uma situação em que os dados retornados do espaço do usuário indicam que há um buffer de 4K. Se o driver realmente precisa retornar apenas 200 bytes, mas retorna 4K no campo Informações, então ocorreu uma vulnerabilidade de divulgação de informações. Esse problema ocorre porque, em versões anteriores do Windows, o buffer usado pelo Gerenciador de E/S para E/S em Buffer não está zerado. Assim, o aplicativo de usuário recebe de volta os 200 bytes originais de dados, mais 4K-200 bytes do conteúdo que estava presente no buffer (conteúdo do pool fora da página). Esse cenário pode ocorrer com todos os usos de E/S em buffer, não apenas com IOCTLs.

Erros na E/S direta de IOCTL

Gerencie corretamente buffers de comprimento zero. Para obter mais informações, consulte Erros de E/S direta.

Erros ao referenciar endereços no espaço de usuário

O código do driver deve fazer uso correto da memória

  • Todas as alocações de pool de drivers devem estar no pool NX (não executável). O uso de pools de memória NX é inerentemente mais seguro do que o uso de pools executáveis não paginados (NP), além de oferecer melhor proteção contra ataques de estouro.

  • Para permitir que os drivers permitam a virtualização HVCI, há requisitos adicionais de memória. Para obter mais informações, consulte Implementar código compatível com HVCI mais adiante neste artigo.

Vulnerabilidades TOCTOU

Existe uma possível vulnerabilidade de tempo de verificação para tempo de uso (TOCTOU) ao usar E/S direta (para IOCTLs ou para leitura/gravação). Lembre-se de que, como o driver está acessando o buffer de dados do usuário, o aplicativo de usuário pode acessar simultaneamente o mesmo buffer de dados.

Para gerenciar esse risco, copie todos os parâmetros que precisam ser validados do buffer de dados do usuário para a memória que só pode ser acessada no modo kernel (como a pilha ou o pool). Em seguida, depois que os dados não puderem ser acessados pelo aplicativo do usuário, valide e, em seguida, opere os dados que foram passados.

Leituras e gravações de registro específicas do modelo MSR

Os intrínsecos do compilador, como __readmsr e __writemsr, podem ser usados para acessar os registros específicos do modelo. Se esse acesso for necessário, o driver sempre deverá verificar se o registro para ler ou gravar está restrito ao índice ou intervalo esperado.

Para obter mais informações e exemplos de código, confira Possibilitar leitura e gravação de MSRs em Práticas recomendadas para restringir o comportamento privilegiado em drivers de modo kernel.

Alças

Objetos de dispositivo

IRPs

Os IRPs (Pacotes de Solicitação de E/S) do Windows são usados para comunicar solicitações de E/S entre o sistema operacional e os drivers do modo kernel, encapsulando todas as informações necessárias no pacote. Os IRPs facilitam a transferência de dados assíncrona, a sincronização e o tratamento de erros, garantindo uma comunicação eficiente e confiável com dispositivos de hardware. Para obter mais informações, consulte pacotes de solicitação de E/S e visão geral do modelo de E/S do Windows.

WDF e IRPs

Uma vantagem de usar o WDF é que os drivers WDF normalmente não acessam diretamente os IRPs. Por exemplo, a estrutura converte os IRPs do WDM que representam operações de leitura, gravação e controle de E/S do dispositivo em objetos de solicitação de estrutura que o KMDF/UMDF recebe em filas de E/S. Sempre que possível, o uso do WDF é altamente recomendado.

Se você precisar escrever um driver WDM, examine as diretrizes a seguir.

Gerencie adequadamente os buffers de E/S de IRP

Examine estes tópicos que abordam como validar valores de entrada IRP:

DispatchReadWrite usando E/S em buffer

Erros na E/S em buffer

DispatchReadWrite usando E/S direta

Erros na E/S direta

Valide valores associados a um IRP, como endereços de buffer e comprimentos.

Se você optou por usar o modo "Neither I/O", lembre-se de que, diferentemente de Leitura e Gravação, e ao contrário de E/S em Buffer e E/S Direta, ao usar o IOCTL em modo Neither I/O, os ponteiros e comprimentos do buffer não são validados pelo Gerenciador de E/S.

Gerencie operações de conclusão de IRP corretamente

Um driver nunca deve concluir um IRP com um valor de status STATUS_SUCCESS, a menos que realmente suporte e processe o IRP. Para obter informações sobre as formas corretas de gerenciar operações de conclusão de IRP, consulte Como concluir IRPs.

Gerencie o estado pendente de IRP do driver

O driver deve marcar o IRP pendente antes de salvar o IRP, considerando a inclusão da chamada para IoMarkIrpPending e a atribuição em uma sequência interligada. Para obter mais informações, consulte Falha ao verificar o estado de um driver e Como reter IRPs de entrada quando um dispositivo está pausado.

Lidar corretamente com as operações de cancelamento de IRP

Pode ser difícil codificar corretamente as operações de cancelamento porque elas normalmente são executadas de forma assíncrona. Os problemas no código que gerencia operações de cancelamento podem passar despercebidos por muito tempo, pois esse código normalmente não é executado com frequência em um sistema em execução. Você deve ler e entender todas as informações apresentadas em Como cancelar IRPs. Preste atenção especial a Sincronização do cancelamento de IRP e Pontos a serem considerados ao cancelar IRPs.

Uma forma recomendada de minimizar os problemas de sincronização associados às operações de cancelamento é implementar uma fila IRP segura contra cancelamento.

Gerencie a limpeza do IRP e feche as operações corretamente

Entenda a diferença entre solicitações IRP_MJ_CLEANUP e IRP_MJ_CLOSE. As solicitações de limpeza chegam depois que um aplicativo fecha todos os identificadores em um objeto de arquivo, mas, às vezes, antes que todas as solicitações de E/S sejam concluídas. As solicitações de fechamento chegam depois que todas as solicitações de E/S para o objeto de arquivo são concluídas ou canceladas. Para obter mais informações, consulte o seguinte:

Rotinas DispatchCreate, DispatchClose e DispatchCreateClose

Rotinas do DispatchCleanup

Erros no tratamento de operações de limpeza e fechamento

Para obter mais informações sobre como gerenciar IRPs corretamente, consulte Erros adicionais ao gerenciar IRPs.

Use funções seguras

Outros problemas de segurança

  • Use um bloqueio ou uma sequência interligada para evitar condições de corrida. Para obter mais informações, consulte Erros em um ambiente multiprocessador.

  • Verifique se nenhum filtro TDI (Transport Driver Interface) de rede ou Provedores de Serviços em Camadas (LSPs) estão instalados pelo driver ou pacotes de software associados durante a instalação ou utilização. Em vez disso, use APIs modernas, como a plataforma de filtragem do Windows (WFP) ).

Vulnerabilidades adicionais de código

Além das possíveis vulnerabilidades abordadas aqui, este artigo fornece informações adicionais para aprimorar a segurança do código do driver em modo kernel: Criando drivers de Kernel-Mode confiáveis.

Para obter informações adicionais sobre a codificação segura de C e C++, consulte Recursos de codificação segura no final deste artigo.

Implemente código compatível com HVCI

Item de lista de verificação de segurança nº 6:Validar se o driver usa memória para que ele seja compatível com HVCI.

Integridade da memória e compatibilidade de HVCI

A integridade da memória, também conhecida como HVCI (integridade de código protegida pelo Hipervisor) usa a tecnologia de hardware e a virtualização para isolar a função de tomada de decisão de CI (Integridade do Código) do restante do sistema operacional. Ao usar a segurança baseada em virtualização para isolar a CI, a única maneira de a memória do kernel se tornar executável é por meio de uma verificação de CI. Isso significa que as páginas de memória do kernel nunca podem ser graváveis e executáveis (W + X), e o código executável não pode ser modificado diretamente.

Para implementar o código compatível com HVCI, verifique se o código do driver faz o seguinte:

  • Aceita o NX por padrão
  • Usa APIs/sinalizadores NX para alocação de memória (NonPagedPoolNx)
  • Não usa seções que são ao mesmo tempo graváveis e executáveis
  • Não tenta modificar diretamente a memória do sistema executável
  • Não usa código dinâmico no kernel
  • Não carrega arquivos de dados como executáveis
  • O alinhamento da seção é um múltiplo de 0x1000 (PAGE_SIZE). Por exemplo, DRIVER_ALIGNMENT=0x1000

Para obter mais informações sobre como usar a ferramenta e uma lista de chamadas de memória incompatíveis, consulte Implementar código compatível com HVCI.

Para obter mais informações sobre o teste de segurança de conceitos básicos do sistema relacionado, consulte Teste de preparação de integridade de código do hipervisor e HVCI (Integridade de código protegida por hipervisor).

Aumente a segurança da instalação do dispositivo

Item de lista de verificação de segurança nº 7:Revise as diretrizes de criação e instalação do driver inf para verificar se você está seguindo as práticas recomendadas.

Ao criar o código que instala o pacote de driver, você deve verificar se a instalação do dispositivo sempre será executada de maneira segura. Uma instalação segura de dispositivo faz o seguinte:

  • Limita o acesso ao dispositivo e suas classes de interface de dispositivo
  • Limita o acesso aos serviços de driver que foram criados para o dispositivo
  • Protege os arquivos de driver contra modificação ou exclusão
  • Limita o acesso às entradas de registro do dispositivo
  • Limita o acesso às classes WMI do dispositivo
  • Usa as funções SetupAPI corretamente

Para obter mais informações, consulte o seguinte:

Configuração Segura de Instalações de Dispositivos

Diretrizes para usar SetupAPI

Usar funções de instalação de dispositivo

Tópicos avançados de instalação de dispositivos e drivers

Siga as práticas recomendadas de código específicas da tecnologia

Item 8 da lista de verificação de segurança:Analise as seguintes diretrizes específicas de tecnologia para o driver.

Sistemas de Arquivos

Para obter mais informações, sobre a segurança do driver do sistema de arquivos, consulte o seguinte:

Introdução à Segurança de Sistemas de Arquivos

Problemas de Segurança do Sistema de Arquivos

Funcionalidades de Segurança para Sistemas de Arquivos

Coexistência com outros drivers de filtro do sistema de arquivos

Iniciativa Microsoft Virus

A MVI (Microsoft Virus Initiative) ajuda as organizações a melhorar as soluções de segurança em que nossos clientes dependem para mantê-las seguras. A Microsoft fornece ferramentas, recursos e conhecimento para dar suporte a experiências mais adequadas, com grande desempenho, confiabilidade e compatibilidade. A Microsoft colabora com parceiros MVI para definir e seguir o SDP (Práticas de Implantação Segura) para dar suporte à segurança e resiliência de nossos clientes mútuos.

Se você for um fornecedor antivírus, consulte Microsoft Virus Initiative para saber como ingressar no MVI para obter mais assistência na implantação de software. Para obter informações sobre como os fornecedores de segurança podem aproveitar melhor as funcionalidades de segurança integrada do Windows para aumentar a segurança e a confiabilidade, consulte práticas recomendadas de Segurança do Windows para integrar e gerenciar ferramentas de segurança.

NDIS – Rede

Para obter informações sobre a segurança do driver NDIS, consulte Problemas de segurança para drivers de rede.

Impressoras

Para obter informações relacionadas à segurança do driver de impressora, consulte considerações sobre a segurança do driver de impressora V4.

Problemas de segurança para drivers WIA (Aquisição de imagem do Windows)

Para obter informações sobre a segurança de WIA, consulte Problemas de segurança para drivers WIA (Aquisição de imagem do Windows).

Adicione as anotações SAL ao seu código de driver

Item 9 da lista de verificação de segurança:adicione anotações SAL ao código do driver.

O SAL (linguagem de anotação de código-fonte) fornece um conjunto de anotações para descrever como uma função usa seus parâmetros, as suposições que ela faz sobre eles e as garantias obtidas ao concluir. As anotações são definidas no arquivo de cabeçalho sal.h. A análise de código do Visual Studio para C++ usa anotações da SAL para modificar a análise de funções. Para obter mais informações sobre o SAL 2.0 para desenvolvimento de driver do Windows, consulte Anotações SAL 2.0 para Drivers do Windows e Usando Anotações SAL para Reduzir Defeitos de Código C/C++.

Para obter informações gerais sobre SAL, consulte este artigo disponível na OSR. SAL Anotações: Não me odeie porque sou bonita

Realizar revisão de código por pares

Item 10 da lista de verificação de segurança:Faça a revisão de código por pares para procurar problemas não identificados por outras ferramentas e processos

Busque revisores de código experientes para procurar problemas que você pode ter deixado passar. Um segundo olhar geralmente encontra problemas que você pode ter esquecido.

Se você não tiver uma equipe adequada para examinar seu código internamente, considere usar ajuda externa para essa finalidade.

Faça uma análise de ameaças

Item 11 da lista de verificação de segurança:Modifique um modelo de ameaça de driver existente ou crie um modelo de ameaça personalizado para o driver.

Ao pensar em segurança, uma metodologia comum é criar modelos de ameaças específicos que tentam descrever os tipos de ataques possíveis. Essa técnica é útil ao projetar um driver, porque força o desenvolvedor a considerar com antecedência os possíveis vetores de ataque contra um driver. Depois de identificar possíveis ameaças, um desenvolvedor de driver pode considerar meios de se defender contra essas ameaças para reforçar a segurança geral do componente do driver.

Este artigo contém diretrizes específicas do driver para criar um modelo de ameaça leve: Modelagem de ameaças para drivers. O artigo mostra como exemplo um diagrama de modelo de ameaça de driver que pode ser usado como ponto de partida para o driver.

Exemplo de diagrama de fluxo de dados que ilustra um driver de modo kernel hipotético.

As práticas recomendadas de SDL (Ciclo de vida de desenvolvimento de segurança) e as ferramentas associadas podem ser usadas por IHVs e OEMs para melhorar a segurança de seus produtos. Para obter mais informações, consulte as Recomendações de SDL para OEMs.

Use o CodeQL para verificar o código do driver

Item de lista de verificação de segurança nº 12:usar o CodeQL para verificar se há vulnerabilidades no código do driver.

O CodeQL, do GitHub, é um mecanismo de análise de código semântico e a combinação de um amplo conjunto de consultas de segurança, juntamente com uma plataforma robusta, o tornam uma ferramenta valiosa para proteger o código do driver. Para obter mais informações, consulte CodeQL e o teste de logotipo de ferramentas estáticas.

Use o Driver Verifier para verificar vulnerabilidades

Item de lista de verificação de segurança nº 13:usar o Verificador de Driver para verificar se há vulnerabilidades no código do driver.

O Driver Verifier usa um conjunto de regras de interface e um modelo do sistema operacional para determinar se o driver interage corretamente com o sistema operacional Windows. O Verificador de Driver encontra defeitos no código do driver que podem apontar para possíveis bugs em drivers.

O Driver Verifier possibilita testar o driver em tempo real. O Driver Verifier monitora drivers em modo kernel do Windows, assim como drivers gráficos, para detectar chamadas de funções ou ações ilegais que podem corromper o sistema. Um depurador anexado permite a exibição da execução do sistema operacional e do código do driver em tempo real. O Driver Verifier pode submeter drivers do Windows a uma variedade de pressões e testes para encontrar comportamentos inadequados. Para obter mais informações, consulte Verificador de Driver.

O Driver Verifer funciona com drivers WDM e KMDF. Para obter as especificidades do que ele pode verificar, consulte os tópicos a seguir.

Para obter mais informações sobre os drivers com os quais o Verificador de Driver pode trabalhar, consulte regras de conformidade de DDI e drivers com suporte. Para obter as regras adicionais do verificador para tipos específicos de drivers, consulte:

Para se familiarizar com o DV, você pode usar um dos drivers de exemplo (por exemplo, o toaster em destaque: https://github.com/Microsoft/Windows-driver-samples/tree/main/general/toaster/toastDrv/kmdf/func/featured).

Verifique o código com os testes do programa de compatibilidade de hardware

Item de lista de verificação de segurança nº 14:Usar os testes do programa de compatibilidade de hardware relacionados à segurança para verificar se há problemas de segurança.

O programa de compatibilidade de hardware inclui testes relacionados à segurança que podem ser usados para procurar vulnerabilidades de código. O Programa de compatibilidade de hardware do Windows usa os testes no HLK (Windows Hardware Lab Kit). Os Testes Fundamentais de Dispositivo HLK podem ser usados na linha de comando para exercitar o código do driver e identificar vulnerabilidades. Para obter informações gerais sobre os testes de conceitos básicos do dispositivo e o programa de compatibilidade de hardware, consulte Windows Hardware Lab Kit.

Os testes a seguir são exemplos que podem ser úteis para buscar comportamentos associados a vulnerabilidades de código do driver:

DF: Teste de IOCTL aleatório de fuzzing (Confiabilidade)

DF: Teste subaberto de fuzzing (Confiabilidade)

DF: Teste de FSCTL de fuzzing do buffer de comprimento zero (Confiabilidade)

DF: Teste de FSCTL aleatório de fuzzing (Confiabilidade)

DF - Teste de API de Fuzz Misc (Confiabilidade)

Você também pode usar o fuzzing de atraso de sincronização do kernel, incluído no Driver Verifier.

Os testes de CHAOS (Concurrent Hardware and Operating System) verificam o driver PnP, testes de fuzzing de driver de dispositivo e testes de sistema de energia simultaneamente. Para obter mais informações, consulte Testes de CHAOS (fundamentos do dispositivo).

Os testes de penetração de fundamentos do dispositivo executam várias formas de ataques de entrada, que são um componente crítico dos testes de segurança. Os testes de ataque e penetração podem ajudar a identificar vulnerabilidades nas interfaces de software. Para obter mais informações, consulte Testes de penetração (fundamentos do dispositivo).

Use o Device Guard – Teste de conformidade, juntamente com as outras ferramentas descritas neste artigo, para confirmar se o driver é compatível com HVCI.

Ferramentas de teste personalizadas e específicas do domínio

Considere o desenvolvimento de testes de segurança personalizados específicos do domínio. Para desenvolver testes adicionais, reúna informações dos designers originais do software, bem como de recursos de desenvolvimento não relacionados familiarizados com o tipo específico de driver que está sendo desenvolvido e de uma ou mais pessoas que conheçam análise e prevenção de invasão de segurança.

Verifique os drivers prontos para envio com ferramentas como BinSkim e SignTool

Item de lista de verificação de segurança nº 15:Verifique o código compilado com as ferramentas como BinSkim e SignTool antes de ser carregado no partner center.

Use ferramentas como BinSkim e SignTool para examinar arquivos binários para verificar o código compilado antes de ser carregado no centro de parceiros para ser distribuído usando o Windows Update. Ter ferramentas em vigor para verificar binários compilados, antes de serem enviadas para distribuição, adiciona outra camada de proteção.

BinSkim

O BinSkim pode identificar práticas de codificação e criação que podem potencialmente tornar o binário vulnerável. O BinSkim verifica:

  • Uso de conjuntos de ferramentas do compilador desatualizados – os binários devem ser compilados em relação aos conjuntos de ferramentas do compilador mais recentes sempre que possível, pois isso maximiza o uso das mitigações de segurança atuais no nível do compilador e fornecidas pelo sistema operacional.
  • Configurações de compilação desprotegidas – os binários devem ser compilados com as configurações mais seguras possíveis para habilitar mitigações de segurança fornecidas pelo sistema operacional, maximizar erros do compilador e relatórios de avisos acionáveis, entre outras coisas.
  • Problemas de assinatura – os binários devem ser assinados com algoritmos de criptografia forte.

O BinSkim é uma ferramenta de código aberto e gera arquivos de saída que usam o formato Static Analysis Results Interchange Format (SARIF) format. BinSkim substitui a antiga ferramenta BinScope.

Para obter mais informações sobre BinSkim, consulte Usar BinSkim para verificar os binários e o Guia do Usuário do BinSkim.

SignTool

Use o SignTool para verificar os arquivos de driver assinados pela versão. Para obter mais informações, consulte Verificando a assinatura de um arquivo de driver de Release-Signed e Confirmando a assinatura de um arquivo de catálogo assinado por um certificado de versão comercial.

Não assine o código do driver de teste em produção

Item 16 da lista de verificação de segurança:Não assine o código de driver de kernel em produção para desenvolvimento, teste e fabricação.

O código de driver de kernel usado para desenvolvimento, teste ou fabricação pode incluir recursos perigosos que representam um risco à segurança. Esse código perigoso nunca deve ser assinado com um certificado que seja confiável para o Windows. O mecanismo correto para executar o código de driver perigoso é desabilitar a Inicialização segura UEFI, habilitar o BCD "TESTSIGNING" e assinar o código de desenvolvimento, teste e fabricação usando um certificado não confiável (por exemplo, um que seja gerado pelo makecert.exe).

O código assinado por um SPC (Certificado de Editores de Software) ou WHQL (Windows Hardware Quality Labs) confiável não deve facilitar o desvio das tecnologias de segurança e integridade de código do Windows. Antes que o código seja assinado por um SPC ou WHQL confiável, primeiro verifique se ele está em conformidade com as diretrizes de Como criar drivers confiáveis no modo kernel. Além disso, o código não deve conter comportamentos perigosos, como descrito abaixo.

Exemplos de comportamentos perigosos incluem o seguinte:

  • Possibilitar o mapeamento de um kernel arbitrário, memória física ou de dispositivo para o modo de usuário.
  • Possibilitar a leitura ou gravação de um kernel arbitrário, memória física ou dispositivo, incluindo entrada/saída (E/S) de porta.
  • Conceder acesso ao armazenamento a ponto de ignorar o controle de acesso do Windows.
  • Possibilitar a modificação de um hardware ou firmware que o driver não foi desenvolvido para gerenciar.

Execute a assinatura digital adequada do driver de lançamento e distribua o seu pacote de drivers através do Windows Update

Item de lista de verificação de segurança nº 17:Usar o portal de parceiros do Windows para enviar seu pacote de driver para ser assinado e distribuído por meio do Windows Update.

Antes de liberar um pacote de driver para o público, você envia o pacote para certificação. Para obter mais informações, consulte Teste de desempenho e compatibilidade e Introdução ao programa de Hardware.

O uso do Windows Update é altamente recomendável para a distribuição de pacotes de driver. O Windows Update fornece um sistema de distribuição robusto, seguro, globalmente dimensionado e compatível com regulamentação que deve ser usado para fornecer atualizações de driver. Para obter mais informações, consulte Como distribuir um pacote de driver.

Use a distribuição gradual e de pré-lançamento do Driver no Partner Center para Windows Hardware para distribuir seu pacote de driver em anéis do Windows Insider definidos, fornecendo monitoramento e avaliação automáticos. Monitore a distribuição do driver usando o de medidas de driver da Microsoft, como porcentagem de computadores sem uma falha no modo Kernel para manter a qualidade.

Para obter uma descrição das práticas seguras de implantação de software, consulte a implantação segura de software CISA: como os fabricantes de software podem garantir a confiabilidade para os clientes.

Entenda como os drivers são reportados usando o Centro de Relatórios de Drivers Vulneráveis e Maliciosos da Microsoft

Item de lista de verificação de segurança nº 18: Entenda como os motoristas são relatados usando o Microsoft Vulnerable and Malicious Driver Reporting Center

Qualquer pessoa pode enviar um driver questionável usando o Microsoft Vulnerable and Malicious Driver Reporting Center. Consulte esta entrada de blog para obter informações sobre como os drivers são enviados para análise - Melhore a segurança do kernel com o novo Microsoft Vulnerable and Malicious Driver Reporting Center

O Reporting Center pode verificar e analisar drivers do Windows criados para arquiteturas x86 e x64. Drivers verificados vulneráveis e mal-intencionados são sinalizados para análise e investigação pela equipe de Drivers vulneráveis da Microsoft. Depois que drivers vulneráveis são confirmados, é enviada uma notificação apropriada e eles são adicionados à lista de bloqueio de drivers vulneráveis. Para mais informações sobre isso, consulte as regras de bloqueio de drivers recomendadas pela Microsoft . Essas regras são aplicadas por padrão a dispositivos habilitados para HVCI (integridade de código protegida por hipervisor) e Windows 10 no modo S.

Examine os recursos de codificação segura

Item 19 da lista de verificação de segurança:Examine esses recursos para entender melhor as práticas recomendadas de codificação segura aplicáveis aos desenvolvedores de driver.

Banco de dados de vulnerabilidade de software conhecido do NIST

O NVD (Banco de Dados de Vulnerabilidade Nacional) é um repositório pesquisável de falhas de software relacionadas à segurança, incluindo drivers do Windows.

Pesquisa no Banco de Dados de Vulnerabilidade NIST

Visão geral do banco de dados de vulnerabilidade nacional

Padrões de codificação seguros

Carnegie Mellon University SEI CERT - Padrão de Codificação em C: Regras para o Desenvolvimento de Sistemas Seguros, Confiáveis e Protegidos (PDF).

MITRE - Weaknesses Addressed by the CERT C Secure Coding Standard

Organizações de codificação segura

Agência de Segurança Cibernética e Infraestrutura (CISA)

Recursos CISA

SAFECode - https://safecode.org/

Carnegie Mellon University SEI CERT

OSR

A OSR fornece treinamento de desenvolvimento de drivers e serviços de consultoria. Esses artigos do boletim informativo da OSR destacam os problemas de segurança do driver.

Nomes, descritores de segurança e classes de dispositivo - Como tornar os objetos de dispositivo acessíveis... e SAFE

You've Gotta Use Protection -- Inside Driver & Device Security

Locking Down Drivers - A Survey of Techniques

Meltdown and Spectre: What about drivers?

Estudo de caso de vulnerabilidade do controlador

From alert to driver vulnerability: Microsoft Defender ATP investigation unearths privilege escalation flaw

Segurança da cadeia de fornecedores de software e SBOMs (Software Bill of Materials)

A iniciativa da Integridade, Transparência e Confiança na Cadeia de Suprimentos (SCITT)

Geração de SBOMs (Notas de Materiais de Software) com SPDX na Microsoft

Microsoft abre o código-fonte de sua ferramenta de geração de lista de materiais de software (SBOM)

Manuais

24 Pecados Mortais de Segurança de Software: Falhas de Programação e Como corrigi-los por Michael Howard, David LeBlanc e John Viega

Writing Secure Software Second Edition, Michael Howard and David LeBlanc

A Arte da Avaliação de Segurança de Software: Identificando e prevenindo vulnerabilidades de software, Mark Dowd, John McDonald e Justin Schuh

Secure Coding in C and C++ (SEI Series in Software Engineering) 2nd Edition, Robert C. Seacord

Programming the Microsoft Windows Driver Model (2nd Edition), Walter Oney

Developing Drivers with the Windows Driver Foundation (Developer Reference), Penny Orwick and Guy Smith

Treinamento

O treinamento em sala de aula do Windows Driver está disponível de fornecedores como os seguintes:

O treinamento online de codificação segura está disponível em várias fontes. Por exemplo, este curso está disponível na Coursera em:

Identificar vulnerabilidades de segurança na programação C/C++.

O SAFECode também oferece treinamento gratuito:

SAFECode.org/training

Certificação profissional

O CERT oferece uma Certificação Profissional em Codificação Segura .

Resumo das principais lições

A segurança do driver é uma tarefa complexa que contém muitos elementos, mas aqui estão alguns pontos-chave a serem considerados:

  • Os drivers residem no kernel do Windows. Problemas ao executar no kernel podem expor todo o sistema operacional. Por isso, preste muita atenção à segurança do driver e projete sempre pensando em segurança.

  • Aplique o princípio de privilégios mínimos:

    a. Use uma cadeia de caracteres SDDL estrita para restringir o acesso ao driver

    b. Restrinja ainda mais os IOCTLs individuais

  • Crie um modelo de ameaça para identificar vetores de ataque e pense em outras restrições que podem ajudar.

  • Tenha cuidado com relação aos ponteiros inseridos que estão sendo passados do modo de usuário. Eles precisam ser investigados, acessados dentro de try except, e são propensos a problemas de tempo de verificação/tempo de uso (ToCToU), a menos que o valor do buffer seja capturado e comparado.

  • Se você não tiver certeza, use METHOD_BUFFERED como um método de buffer IOCTL.

  • Use utilitários de verificação de código, como CodeQL, para procurar vulnerabilidades de código conhecidas e corrigir quaisquer problemas identificados.

  • Busque revisores de código experientes para procurar problemas que você pode ter deixado passar.

  • Use o Driver Verifier e teste o driver com várias entradas, incluindo casos menos frequentes.