Lire en anglais

Partager via


Liste de contrôle de sécurité du pilote

Cet article fournit une liste de contrôle de sécurité des pilotes pour les développeurs de pilotes afin de réduire le risque de compromission des pilotes.

Vue d’ensemble de la sécurité des pilotes

Une faille de sécurité est toute faille qui permet à un attaquant de provoquer un dysfonctionnement d’un pilote de telle sorte qu’il provoque le blocage du système ou de devenir inutilisable. En outre, les vulnérabilités dans le code du pilote peuvent permettre à un attaquant d’accéder au noyau, créant ainsi une possibilité de compromettre l’ensemble du système d’exploitation. Lorsque la plupart des développeurs travaillent sur leur pilote, ils se concentrent sur le bon fonctionnement du pilote, et non sur la façon dont un attaquant malveillant tentera d’exploiter les vulnérabilités au sein de son code.

Une fois qu’un pilote est libéré, toutefois, les attaquants peuvent tenter de sonder et d’identifier les failles de sécurité. Les développeurs doivent prendre en compte ces problèmes pendant la phase de conception et d’implémentation afin de réduire la probabilité de telles vulnérabilités. L’objectif est d’éliminer toutes les failles de sécurité connues avant que le pilote ne soit libéré.

La création de pilotes plus sécurisés nécessite la coopération de l’architecte système (en pensant consciemment aux menaces potentielles au pilote), le développeur implémentant le code (opérations courantes de codage défensif qui peuvent être la source d’exploits) et l’équipe de test (essayant de trouver de manière proactive la faiblesse et les vulnérabilités). En coordonnant correctement toutes ces activités, la sécurité du conducteur est considérablement améliorée.

En plus d’éviter les problèmes associés à un pilote attaqué, de nombreuses étapes décrites, telles que l’utilisation plus précise de la mémoire du noyau, augmenteront la fiabilité de votre pilote. Cela réduira les coûts de support et augmentera la satisfaction des clients avec votre produit. La réalisation des tâches dans la liste de contrôle ci-dessous vous aidera à atteindre tous ces objectifs.

liste de contrôle de sécurité :Effectuer la tâche de sécurité décrite dans chacune de ces rubriques.

Case à cocher non marquée représentant un élément de la liste de vérification de la sécurité. Confirmez qu’un pilote de noyau est nécessaire

Case à cocher non marquée représentant un élément de la liste de vérification de la sécurité. Utiliser les frameworks de pilotes

Case à cocher non marquée représentant un élément de la liste de vérification de la sécurité. Contrôler l’accès aux pilotes logiciels uniquement

Case à cocher non marquée représentant un élément de la liste de vérification de la sécurité. Ne pas signer le code du pilote de test de production

case à cocher non marquée représentant un élément dans la liste de contrôle de sécurité.effectuer une analyse des menaces

Case à cocher non marquée représentant un élément de la liste de vérification de la sécurité. Suivez les instructions de codage sécurisé du pilote

case à cocher non marquée représentant un élément dans la liste de contrôle de sécurité.Implémenter le code compatible HVCI

case à cocher non marquée représentant un élément dans la liste de contrôle de sécurité.Suivre les meilleures pratiques de code spécifiques à la technologie

Case à cocher non marquée représentant un élément de la liste de vérification de la sécurité. Effectuer une révision de code homologue

case à cocher non marquée représentant un élément dans la liste de contrôle de sécurité.Gérer le contrôle d’accès des pilotes

case à cocher non marquée représentant un élément dans la liste de contrôle de sécurité.Améliorer la sécurité de l’installation des appareils

Case à cocher non marquée représentant un élément de la liste de vérification de la sécurité. Exécuter une signature appropriée du pilote de mise en production

Case à cocher non marquée représentant un élément de la liste de vérification de la sécurité. Utiliser CodeQL pour vérifier le code de votre pilote

Une case à cocher non marquée représentant un élément de la liste de contrôle de sécurité.Ajoutez des annotations SAL à votre code de pilote

Case à cocher non marquée représentant un élément de la liste de vérification de la sécurité. Utiliser le vérificateur de pilotes pour rechercher les vulnérabilités

case à cocher non marquée représentant un élément dans la liste de contrôle de sécurité.Vérifier le code avec le BinSkim Binary Analyzer

case à cocher non marquée représentant un élément dans la liste de contrôle de sécurité.Vérifier le code avec les tests du programme de compatibilité matérielle

case à cocher non marquée représentant un élément dans la liste de contrôle de sécurité.Comprendre comment les pilotes sont signalés à l’aide du Centre de rapports de pilotes vulnérables et malveillants Microsoft

case à cocher non marquée représentant un élément dans la liste de contrôle de sécurité.Vérifier les ressources de codage sécurisées

case à cocher non marquée représentant un élément dans la liste de contrôle de sécurité. Examiner le résumé des points clés

Vérifiez qu’un pilote de noyau est requis

élément de liste de contrôle de sécurité n°1 :Confirmer qu’un pilote de noyau est requis et qu’une approche à risque moindre, telle que le service ou l’application Windows, n’est pas une meilleure option.

Les pilotes résident dans le noyau Windows, et un problème lors de l'exécution noyau peut exposer tout le système d'exploitation. Si une autre option est disponible, il sera probablement moins coûteux et présente moins de risques que la création d’un nouveau pilote de noyau. Pour plus d’informations sur l’utilisation des pilotes Windows intégrés, consultez Devez-vous écrire un pilote ?.

Pour plus d’informations sur l’utilisation des tâches en arrière-plan, consultez Prendre en charge votre application avec des tâches en arrière-plan.

Pour plus d’informations sur l’utilisation des services Windows, consultez Services.

Utilisez les frameworks de pilotes

Élément de liste de contrôle de sécurité n°2 : Utilisez les frameworks de pilotes pour réduire la taille de votre code et augmenter sa fiabilité et sa sécurité.

Utilisez les frameworks de pilotes Windows pour réduire la taille de votre code et augmenter sa fiabilité et sa sécurité. Pour commencer, consultez l’utilisation de WDF pour développer un pilote. Pour plus d’informations sur l’utilisation du pilote d’infrastructure en mode utilisateur à faible risque (UMDF), consultez Choix d’un modèle de pilote.

Écrire un pilote Windows ancien modèle Windows Driver Model (WDM) est plus fastidieux, coûteux et implique presque toujours de recréer du code disponible dans les frameworks de drivers.

Le code source windows Driver Framework est open source et disponible sur GitHub. Il s’agit du même code source à partir duquel la bibliothèque runtime WDF fournie dans Windows 10 est générée. Vous pouvez déboguer votre pilote plus efficacement lorsque vous pouvez suivre les interactions entre le pilote et WDF. Téléchargez-le depuis https://github.com/Microsoft/Windows-Driver-Frameworks.

Contrôlez l’accès aux pilotes logiciels uniquement

élément de liste de contrôle de sécurité n° 3 :Si un pilote logiciel uniquement sera créé, un contrôle d’accès supplémentaire doit être implémenté.

Les pilotes de noyau uniquement logiciels n’utilisent pas de plug-and-play (PnP) pour devenir associés à des ID matériels spécifiques et peuvent s’exécuter sur n’importe quel PC. Un tel pilote peut être utilisé à des fins autres que celle initialement prévue, créant un vecteur d’attaque.

Étant donné que les pilotes de noyau uniquement logiciels contiennent un risque supplémentaire, ils doivent être limités à s’exécuter sur du matériel spécifique (par exemple, à l’aide d’un ID PnP unique pour permettre la création d’un pilote PnP, ou en vérifiant la table SMBIOS pour la présence d’un matériel spécifique).

Par exemple, imaginez que l’OEM Fabrikam souhaite distribuer un pilote permettant une utilité d’overclocking pour leurs systèmes. Si ce pilote uniquement logiciel devait s'exécuter sur un système d’un autre OEM, cela pourrait entraîner une instabilité du système ou des dommages. Les systèmes de Fabrikam doivent inclure un ID PnP unique pour permettre la création d’un pilote PnP pouvant également être mis à jour via Windows Update. Si cela n’est pas possible et que Fabrikam crée un pilote hérité, ce pilote doit trouver une autre méthode pour vérifier qu’il s’exécute sur un système Fabrikam (par exemple, en examinant la table SMBIOS avant d’activer les fonctionnalités).

Ne signez pas le code de test en production

Élément de liste de contrôle de sécurité n° 4 : Ne signez pas le code de développement, de test et de fabrication des pilotes de noyau en production.

Le code de pilote du noyau utilisé pour le développement, les tests ou la fabrication peut inclure des fonctionnalités dangereuses qui présentent un risque de sécurité. Ce code dangereux ne doit jamais être signé avec un certificat approuvé par Windows. Le mécanisme approprié pour l’exécution de code de pilote dangereux consiste à désactiver le démarrage sécurisé UEFI, à activer le BCD « TESTSIGNING » et à signer le code de développement, de test et de fabrication à l’aide d’un certificat non approuvé (par exemple, un généré par makecert.exe).

Le code signé par un certificat SPC (Software Publishers Certificate) approuvé ou une signature WHQL (Hardware Quality Labs) windows ne doit pas faciliter le contournement des technologies d’intégrité et de sécurité du code Windows. Avant que le code ne soit signé par une signature SPC ou WHQL approuvée, vérifiez d’abord qu’il est conforme aux instructions de Création de pilotes fiables Kernel-Mode. En outre, le code ne doit contenir aucun comportement dangereux, décrit ci-dessous. Pour plus d’informations sur la signature des pilotes, veuillez consulter La signature du pilote release plus loin dans cet article.

Voici quelques exemples de comportement dangereux :

  • Fournir la possibilité de mapper de manière arbitraire la mémoire du noyau, physique ou d’un appareil au mode utilisateur.
  • Fournir la capacité de lire ou d’écrire une mémoire arbitraire du noyau, physique ou de l’appareil, y compris l’entrée/sortie de port (E/S).
  • Fournir l’accès au stockage qui contourne le contrôle d’accès Windows.
  • Fournir la possibilité de modifier le matériel ou le microprogramme que le pilote n’a pas été conçu pour gérer.

Effectuer une analyse des menaces

élément de liste de contrôle de sécurité n° 5 :modifier un modèle de menace de pilote existant ou créer un modèle de menace personnalisé pour votre pilote.

En tenant compte de la sécurité, une méthodologie courante consiste à créer des modèles de menace spécifiques qui tentent de décrire les types d’attaques possibles. Cette technique est utile lors de la conception d’un pilote, car elle force le développeur à prendre en compte les vecteurs d’attaque potentiels contre un pilote à l’avance. Après avoir identifié des menaces potentielles, un développeur de pilotes peut alors envisager de défendre contre ces menaces afin de renforcer la sécurité globale du composant pilote.

Cet article fournit des conseils spécifiques au pilote pour la création d’un modèle de menace léger : modélisation des menaces pour les pilotes. L’article fournit un exemple de diagramme de modèle de menace de pilote qui peut être utilisé comme point de départ pour votre pilote.

Exemple de diagramme de flux de données illustrant un pilote hypothétique en mode noyau.

Les meilleures pratiques de cycle de vie du développement de la sécurité (SDL) et les outils associés peuvent être utilisés par les IMV et les OEM pour améliorer la sécurité de leurs produits. Pour plus d’informations, consultez SDL recommendations for OEMs.

Suivez les instructions de codage sécurisé du pilote

élément de liste de contrôle de sécurité n° 6 :passez en revue votre code et supprimez les vulnérabilités de code connues.

L’activité principale de la création de pilotes sécurisés identifie les zones du code qui doivent être modifiées pour éviter les vulnérabilités logicielles connues. La plupart de ces vulnérabilités logicielles connues concernent le suivi strict de l'utilisation de la mémoire pour éviter les problèmes lorsque d'autres écrasent ou compromettent les emplacements mémoire que votre pilote utilise.

Les outils d’analyse du code, tels que CodeQL et les tests spécifiques au pilote, peuvent être utilisés pour vous aider à localiser, certains, mais pas tous, de ces vulnérabilités. Ces outils et tests sont décrits plus loin dans cette rubrique.

Tampons de mémoire

Utilisez la méthode appropriée pour accéder aux mémoires tampons de données avec des IOCTLs

L’une des principales responsabilités d’un pilote Windows consiste à transférer des données entre les applications en mode utilisateur et les appareils d’un système. Les trois méthodes d’accès aux mémoires tampons de données sont indiquées dans le tableau suivant.

Type de mémoire tampon IOCTL Résumé Pour plus d’informations
METHOD_BUFFERED Recommandé pour la plupart des situtations Utilisation des E/S en mémoire tampon
METHOD_IN_DIRECT ou METHOD_OUT_DIRECT Utilisé dans certaines E/S HW à grande vitesse Utilisation des E/S directes
METHOD_NEITHER Éviter si possible Utilisation des entrées/sorties directes et non tamponnées

En général, les E/S mises en mémoire tampon sont recommandées, car elles fournissent les méthodes de mise en mémoire tampon les plus sécurisées. Toutefois, même lors de l’utilisation d’E/S mises en mémoire tampon, il existe des risques, tels que des pointeurs incorporés qui doivent être atténués.

Pour plus d’informations sur l’utilisation des mémoires tampons dans iocTLs, consultez Méthodes d’accès aux mémoires tampons de données.

Erreurs d’utilisation de l’E/S mis en tampon IOCTL

  • Vérifiez la taille des mémoires tampons associées à IOCTL. Pour plus d’informations, consultez Échec de vérification de la taille des mémoires tampons.

  • Initialisez correctement les mémoires tampons de sortie. Pour plus d’informations, consultez Échec d’initialisation des buffers de sortie.

  • Validez correctement les mémoires tampons de longueur variable. Pour plus d’informations, consultez Échec de validation des mémoires tampons Variable-Length.

  • Lorsque vous utilisez l’E/S mis en tampon, assurez-vous de retourner la longueur correcte pour le OutputBuffer dans le champ Information de la structure IO_STATUS_BLOCK. Ne retournez pas directement la longueur directement à partir d’une requête READ. Par exemple, considérez une situation où les données retournées à partir de l’espace utilisateur indiquent qu’il existe une mémoire tampon 4K. Si le pilote ne doit retourner que 200 octets, mais retourne simplement 4K dans le champ Informations, une vulnérabilité de divulgation d’informations s’est produite. Ce problème se produit car dans les versions antérieures de Windows, la mémoire tampon utilisée par le Gestionnaire d’E/S pour les E/S mises en mémoire tampon n’est pas zéro. Ainsi, l'application utilisateur récupère les 200 octets d'origine des données, plus les 4K-200 octets restants de ce qui se trouvait dans la mémoire tampon (contenu du pool non paginé). Ce scénario peut se produire avec toutes les utilisations d’E/S mises en mémoire tampon et pas seulement avec les IOCTL.

Erreurs dans l’E/S direct IOCTL

Gérez correctement les mémoires tampons de longueur nulle. Pour plus d’informations, consultez Errors in Direct E/S.

Erreurs dans le référencement d’adresses d’espace utilisateur

Lectures et écritures de MSR (model-specific register)

Les intrinsèques du compilateur, telles que __readmsr et __writemsr peuvent être utilisées pour accéder aux registres spécifiques au modèle. Si cet accès est requis, le pilote doit toujours vérifier que le registre à lire ou à écrire est limité à l’index ou à la plage attendu.

Pour plus d’informations et des exemples de code, veuillez consulter la rubrique Fournir la possibilité de lire/écrire des MSR dans les bonnes pratiques de sécurité de développement pour les développeurs de pilotes Windows.

Vulnérabilités TOCTOU

Il existe une vulnérabilité potentielle de vérification de l’heure à l’utilisation de l’heure (TOCTOU) lors de l’utilisation de l’E/S direct (pour les IOCTL ou pour Read/Write). N’oubliez pas que le pilote accède à la mémoire tampon de données utilisateur, l’utilisateur peut y accéder simultanément.

Pour gérer ce risque, copiez tous les paramètres qui doivent être validés à partir de la mémoire tampon de données utilisateur en mémoire uniquement accessible à partir du mode noyau (par exemple, la pile ou le pool). Ensuite, une fois que les données ne sont pas accessibles par l’application utilisateur, validez et utilisez les données transmises.

Le code du pilote doit utiliser correctement la mémoire

  • Toutes les allocations de pool de pilotes doivent être dans le pool non exécutable (NX). Utiliser des pools de mémoire NX est intrinsèquement plus sécurisé que d’utiliser des pools non paginés (NP) exécutables et offre une meilleure protection contre les attaques de débordement.

  • Les pilotes de périphérique doivent gérer correctement différents modes utilisateur, ainsi que les demandes d’E/S du noyau vers le noyau.

Pour permettre aux pilotes de prendre en charge la virtualisation HVCI, il existe des besoins en mémoire supplémentaires. Pour plus d’informations, consultez Implémenter le code compatible HVCI plus loin dans cet article.

Poignées

Objets de l’appareil

Plans de ressources intégrés (IRPs)

WDF et IRPs

L’un des avantages de l’utilisation de WDF est que les pilotes WDF n’accèdent généralement pas directement aux IRPs. Par exemple, le framework convertit les IRP WDM représentant les opérations de contrôle de lecture, d’écriture et de périphérique en objets de requête du framework que KMDF/UMDF reçoit dans les files d’attente E/S.

Si vous rédigez un pilote WDM, consultez les conseils suivants.

Gérez correctement les tampons E/S des IRP

Les articles suivants fournissent des informations sur la validation des valeurs d’entrée IRP :

DispatchReadWrite utilisant des E/S tamponnées

Erreurs dans les E/S en mémoire tampon

DispatchReadWrite utilisant des E/S directes

Erreurs dans les E/S directes

Problèmes de sécurité pour les codes de contrôle d’E/S

Envisagez de valider les valeurs associées à un IRP, telles que les adresses de mémoire tampon et les longueurs.

Si vous avez choisi d'utiliser le mode Neither I/O, sachez que, contrairement à la lecture et à l'écriture, et contrairement aux E/S mises en mémoire tampon et aux E/S directes, lorsque vous utilisez le mode Neither I/O avec IOCTL, les pointeurs de mémoire tampon et les longueurs ne sont pas validés par le gestionnaire d'E/S.

Gérez correctement les opérations de complétion des IRP

Un pilote ne doit jamais terminer un IRP avec une valeur de statut de STATUS_SUCCESS à moins qu’il ne prenne réellement en charge et ne traite l’IRP. Pour plus d'informations sur les méthodes appropriées pour gérer les opérations de finalisation des IRP, consultez : Fin des IRPs.

Gérez l’état en attente des IRP du pilote

Le pilote doit marquer l’IRP comme étant en attente avant de sauvegarder l’IRP, et devrait envisager d’inclure à la fois l’appel à IoMarkIrpPending et l’affectation dans une séquence imbriquée. Pour plus d’informations, consultez la rubrique Échec de la vérification de l’état d’un pilote et Conservation des IRPs entrants lorsqu’un appareil est suspendu.

Gérer correctement les opérations d’annulation IRP

Les opérations d’annulation peuvent être difficiles à coder correctement, car elles s’exécutent généralement de manière asynchrone. Les problèmes dans le code qui gère les opérations d’annulation peuvent passer inaperçus pendant une longue période, car ce code n’est généralement pas exécuté fréquemment dans un système en cours d’exécution. Veillez à lire et à comprendre toutes les informations fournies sous Annulation des IRPs. Portez une attention particulière à la Synchronisation de l’annulation d’une IRP et aux Points à prendre en compte lors de l’annulation d’IRP.

Une méthode recommandée pour minimiser les problèmes de synchronisation associés aux opérations d’annulation est de mettre en œuvre une File d’attente IRP sécurisée contre les annulations.

Gérer correctement les opérations de nettoyage et de fermeture de l'IRP

Veillez à comprendre la différence entre les requêtes IRP_MJ_CLEANUP et IRP_MJ_CLOSE. Les demandes de nettoyage arrivent une fois qu’une application ferme tous les handles d’un objet de fichier, mais parfois avant la fin de toutes les demandes d’E/S. Les demandes de fermeture arrivent après que toutes les demandes d’E/S pour le fichier ont été terminées ou annulées. Pour plus d’informations, consultez les articles suivants :

Routines DispatchCreate, DispatchClose et DispatchCreateClose

Routines DispatchCleanup

Erreurs dans la gestion des opérations de nettoyage et de fermeture

Pour plus d’informations sur la gestion correcte des IRPs, consultez Erreurs supplémentaires dans la gestion des irPs.

Autres problèmes de sécurité

  • Utilisez un verrou ou une séquence interverrouillée pour éviter les conditions de course. Pour plus d’informations, consultez Erreurs dans un environnement multiprocesseur.

  • Assurez-vous que les pilotes de périphérique gèrent correctement les requêtes d’E/S en mode utilisateur ainsi que les requêtes d’E/S de noyau à noyau.

  • Assurez-vous qu’aucun filtre TDI ou LSP n’est installé par le pilote ou les packages logiciels associés lors de l’installation ou de l’utilisation.

Utiliser des fonctions sécurisées

Vulnérabilités de code supplémentaires

En plus des vulnérabilités possibles décrites ici, cet article fournit des informations supplémentaires sur l’amélioration de la sécurité du code de pilote en mode noyau : Création de pilotes fiables Kernel-Mode.

Pour plus d’informations sur le codage sécurisé C et C++, consultez ressources de codage sécurisées à la fin de cet article.

Gérer le contrôle d’accès au pilote

Élément de liste de contrôle de sécurité n° 7 : Examinez votre pilote pour vous assurer que vous contrôlez correctement l’accès.

Gestion du contrôle d’accès au pilote - WDF

Les pilotes doivent s'efforcer d'empêcher les utilisateurs d’avoir un accès inapproprié aux appareils et fichiers d’un ordinateur. Pour empêcher l’accès non autorisé aux appareils et aux fichiers, vous devez :

  • Nommez les objets d’appareil uniquement si nécessaire. Les objets d'appareil nommés sont généralement nécessaires uniquement pour des raisons de compatibilité, par exemple si vous disposez d'une application qui s'attend à ouvrir l'appareil à l'aide d'un nom particulier ou si vous utilisez un appareil ou un dispositif de contrôle non PNP. Notez que les pilotes WDF n’ont pas besoin de nommer leur FDO d’appareil PnP pour créer un lien symbolique en utilisant WdfDeviceCreateSymbolicLink.

  • Sécuriser l’accès aux objets et interfaces de l’appareil.

Pour permettre aux applications ou à d’autres pilotes WDF d’accéder à votre PDO d’appareil PnP, vous devez utiliser des interfaces d’appareil. Pour plus d’informations, consultez Utilisation des interfaces d’appareil. Une interface d’appareil sert de lien symbolique vers le PDO de la pile de votre appareil.

L'une des meilleures façons de contrôler l'accès au PDO consiste à spécifier une chaîne SDDL dans votre fichier INF. Si la chaîne SDDL n’est pas dans le fichier INF, Windows applique un descripteur de sécurité par défaut. Pour plus d’informations, consultez Sécurisation des objets d’appareil et SDDL pour les objets d’appareil.

Pour plus d’informations sur le contrôle de l’accès, consultez les articles suivants :

Contrôle de l'accès aux dispositifs dans les pilotes KMDF

Noms, descripteurs de sécurité et classes d’appareil - Rendre les objets d’appareil accessibles... et SAFE tiré de The NT Insider Newsletter Janvier Février 2017 publié par OSR.

Gestion du contrôle d’accès au pilote - WDM

Si vous utilisez un pilote WDM et que vous avez utilisé un objet d’appareil nommé, vous pouvez utiliser IoCreateDeviceSecure et spécifier un SDDL pour le sécuriser. Lorsque vous implémentez IoCreateDeviceSecure spécifiez toujours un GUID de classe personnalisé pour DeviceClassGuid. Vous ne devez pas spécifier un GUID de classe existant ici. Cela a le potentiel d’interrompre les paramètres de sécurité ou la compatibilité pour d’autres appareils appartenant à cette classe. Pour plus d’informations, consultez WdmlibIoCreateDeviceSecure.

Pour plus d’informations, consultez les articles suivants :

Contrôle de l'accès aux appareils

Contrôle de l'accès à l'espace noms des appareils

modèle de sécurité Windows pour les développeurs de pilotes

Hiérarchie des risques d’identificateurs de sécurité (SID)

La section suivante décrit la hiérarchie des risques des SID courants utilisés dans le code du pilote. Pour obtenir des informations générales sur SDDL, consultez SDDL pour les objets d’appareil, chaînes SIDet syntaxe de chaîne SDDL.

Il est important de comprendre que si les appelants à privilèges inférieurs sont autorisés à accéder au noyau, le risque de code est accru. Dans ce diagramme de résumé, le risque augmente lorsque vous autorisez des SID de privilèges inférieurs à accéder à vos fonctionnalités de pilote.

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

En suivant le principe général de sécurité des privilèges minimum, configurez uniquement le niveau minimal d’accès requis pour que votre pilote fonctionne.

Contrôle granulaire de la sécurité IOCTL de WDM

Pour gérer davantage la sécurité lorsque les IOCTL sont envoyés par les appelants en mode utilisateur, le code du pilote peut inclure la fonction IoValidateDeviceIoControlAccess. Cette fonction permet à un pilote de vérifier les droits d’accès. Lors de la réception d’un IOCTL, un pilote peut appeler IoValidateDeviceIoControlAccess, en spécifiant FILE_READ_ACCESS, FILE_WRITE_ACCESS ou les deux.

L’implémentation d’un contrôle de sécurité IOCTL granulaire ne remplace pas la nécessité de gérer l’accès des pilotes à l’aide des techniques décrites ci-dessus.

Pour plus d’informations, consultez les articles suivants :

définition des codes de contrôle d’E/S

Implémenter le code compatible HVCI

élément de liste de contrôle de sécurité n° 8 :Vérifiez que votre pilote utilise la mémoire pour garantir sa compatibilité avec HVCI.

Utilisation de la mémoire et compatibilité HVCI

HVCI utilise la technologie matérielle et la virtualisation pour isoler la fonction décisionnaire d’intégrité du code (CI) du reste du système d’exploitation. Lorsque vous utilisez la sécurité basée sur la virtualisation pour isoler l'IC, la mémoire du noyau ne peut devenir exécutable qu'à travers une vérification de l'IC. Cela signifie que les pages de mémoire du noyau ne peuvent jamais être à la fois modifiables (écriture) et exécutables (W+X), et que le code exécutable ne peut pas être modifié directement.

Pour implémenter du code compatible HVCI, vérifiez que votre code de pilote effectue les opérations suivantes :

  • Opte pour NX par défaut
  • Utilise les API/indicateurs NX pour l’allocation de mémoire (NonPagedPoolNx)
  • N’utilise pas les sections qui sont à la fois accessibles en écriture et exécutables
  • Ne tente pas de modifier directement la mémoire système exécutable
  • N’utilise pas de code dynamique dans le noyau
  • Ne charge pas les fichiers de données en tant qu’exécutables
  • L’alignement des sections est un multiple de 0x1000 (PAGE_SIZE). Par exemple, DRIVER_ALIGNMENT=0x1000

Pour plus d’informations sur l’utilisation de l’outil et une liste d’appels de mémoire incompatibles, consultez Implémenter le code compatible HVCI.

Pour plus d’informations sur le test de sécurité des fondamentaux du système, veuillez consulter les section Test de préparation de l’intégrité du code HyperVisor et Intégrité du code protégé par hyperviseur (HVCI).

Suivez les meilleures pratiques de code spécifiques à la technologie

Élément de liste de contrôle de sécurité n° 9 : Examinez les conseils spécifiques à la technologie pour votre pilote.

Systèmes de fichiers

Pour plus d’informations, sur la sécurité des pilotes du système de fichiers, consultez les articles suivants :

Introduction à la sécurité des systèmes de fichiers

problèmes de sécurité du système de fichiers

fonctionnalités de sécurité pour les systèmes de fichiers

Coexistence avec d’autres pilotes de filtre de système de fichiers

NDIS - Mise en réseau

Pour plus d’informations sur la sécurité des pilotes NDIS, consultez Problèmes de sécurité pour les pilotes réseau.

Affichage

Pour des informations sur la sécurité des pilotes d’affichage, consultez la rubrique <Contenu en attente>.

Imprimantes

Pour plus d’informations sur la sécurité des pilotes d’imprimante, consultez Considérations relatives à la sécurité du pilote d’imprimante V4.

Problèmes de sécurité pour les pilotes WIA (Windows Image Acquisition)

Pour plus d’informations sur la sécurité WIA, consultez Problèmes de sécurité pour les pilotes WIA (Windows Image Acquisition).

Améliorer la sécurité de l’installation des appareils

Élément de liste de contrôle de sécurité #10 : Examinez les directives de création et d’installation des fichiers INF des pilotes pour vous assurer que vous suivez les bonnes pratiques.

Lorsque vous créez le code qui installe votre pilote, vous devez vous assurer que l’installation de votre appareil sera toujours effectuée de manière sécurisée. Une installation sécurisée de l’appareil est l’une des opérations suivantes :

  • Limite l’accès à l’appareil et à ses classes d’interface d’appareil
  • Limite l’accès aux services de pilote créés pour l’appareil
  • Protège les fichiers du pilote contre la modification ou la suppression
  • Limite l’accès aux entrées de Registre de l’appareil
  • Limite l’accès aux classes WMI de l’appareil
  • Utilise correctement les fonctions SetupAPI

Pour plus d’informations, consultez les articles suivants :

Création d’installations sécurisées de dispositifs

Lignes directrices pour l'utilisation de SetupAPI

Utilisation des fonctions d'installation des appareils

Rubriques avancées sur l'installation de périphériques et des pilotes

Effectuer une révision de code par les pairs

élément de liste de contrôle de sécurité n° 11 :Effectuer une révision de code homologue pour rechercher les problèmes non exposés par les autres outils et processus

Recherchez des réviseurs de code compétents pour rechercher des problèmes que vous avez peut-être manqués. Un deuxième ensemble d’yeux verra souvent des problèmes que vous pourriez avoir négligés.

Si vous n’avez pas de personnel approprié pour passer en revue votre code en interne, envisagez d’engager de l’aide extérieure à cet effet.

Exécutez une signature de pilote de version correcte

élément de liste de contrôle de sécurité n° 12 :Utiliser le portail partenaire Windows pour signer correctement votre pilote pour la distribution.

Avant de publier un package de pilotes au public, nous vous recommandons de soumettre le package à des fins de certification. Pour plus d’informations, consultez Test de performance et de compatibilité, Prise en main du programme matériel, Services du tableau de bord matérielet Attestation de signature d’un pilote de noyau pour la publication publique.

Utiliser CodeQL pour vérifier le code de votre pilote

élément de liste de contrôle de sécurité n° 13 :Utiliser CodeQL pour rechercher les vulnérabilités dans votre code de pilote.

CodeQL, par GitHub, est un moteur d’analyse de code sémantique et la combinaison d’une suite étendue de requêtes de sécurité, ainsi qu’une plateforme robuste, constituent un outil précieux pour sécuriser le code du pilote. Pour plus d’informations, consultez CodeQL et le test du logo Static Tools.

Ajouter des annotations SAL à votre code de pilote

élément de liste de contrôle de sécurité n° 14 :Ajouter des annotations SAL dans votre code de pilote.

Le langage d’annotation de code source (SAL) fournit un ensemble d’annotations que vous pouvez utiliser pour décrire la façon dont une fonction utilise ses paramètres, les hypothèses qu’elle effectue à leur sujet et les garanties qu’elle effectue quand elle se termine. Les annotations sont définies dans le fichier d’en-tête sal.h. L’analyse du code Visual Studio pour C++ utilise des annotations SAL pour modifier son analyse des fonctions. Pour plus d’informations sur le développement de pilotes SAL 2.0 pour Windows, consultez annotations SAL 2.0 pour les pilotes Windows et à l’aide d’annotations SAL pour réduire les défauts de code C/C++.

Pour obtenir des informations générales sur sal, reportez-vous à cet article disponible à partir d’OSR. https://www.osr.com/blog/2015/02/23/sal-annotations-dont-hate-im-beautiful/

Utiliser le vérificateur de pilotes pour rechercher les vulnérabilités

élément de liste de contrôle de sécurité n° 15 :Utiliser le vérificateur de pilotes pour vérifier les vulnérabilités dans votre code de pilote.

Le vérificateur de pilotes utilise un ensemble de règles d’interface et un modèle du système d’exploitation pour déterminer si le pilote interagit correctement avec le système d’exploitation Windows. DV trouve des défauts dans le code du pilote qui pourraient indiquer des bugs potentiels dans les pilotes.

Le vérificateur de pilotes permet de tester en direct le pilote. Le Driver Verifier surveille les pilotes en mode noyau de Windows et les pilotes graphiques pour détecter les appels de fonction ou actions illégales susceptibles de corrompre le système. Le vérificateur de pilotes peut soumettre les pilotes Windows à diverses contraintes et tests pour trouver un comportement incorrect. Pour plus d’informations, consultez Type de débogage.

Notez que seuls certains types de pilotes sont pris en charge par DV. Pour plus d’informations sur les pilotes que DV peut vérifier, consultez Pilotes pris en charge. Reportez-vous aux pages suivantes pour plus d’informations sur les tests DV disponibles pour le type de pilote avec lequel vous travaillez.

Pour vous familiariser avec DV, vous pouvez utiliser l’un des pilotes d’exemple (par exemple, l’échantillon de toaster en vedette : https://github.com/Microsoft/Windows-driver-samples/tree/main/general/toaster/toastDrv/kmdf/func/featured).

Vérifier le code avec l’analyseur binaire BinSkim

élément de liste de contrôle de sécurité n° 16 :Suivez ces étapes pour utiliser BinSkim pour vérifier que les options de compilation et de génération sont configurées pour réduire les problèmes de sécurité connus.

Utilisez BinSkim pour examiner les fichiers binaires pour identifier les pratiques de codage et de création qui peuvent potentiellement rendre le fichier binaire vulnérable.

BinSkim vérifie les points suivants :

  • Utilisation des ensembles d’outils de compilateur obsolètes : les fichiers binaires doivent être compilés sur les ensembles d’outils de compilateur les plus récents dans la mesure du possible pour optimiser l’utilisation des atténuations de sécurité actuelles au niveau du compilateur et du système d’exploitation.
  • Paramètres de compilation non sécurisés : les fichiers binaires doivent être compilés avec les paramètres les plus sécurisés possibles pour activer les atténuations de sécurité fournies par le système d’exploitation, optimiser les erreurs du compilateur et les rapports d’avertissements actionnables, entre autres.
  • Problèmes de signature : les fichiers binaires signés doivent être signés avec des algorithmes forts par chiffrement.

BinSkim est un outil open source et génère des fichiers de sortie qui utilisent le format d’échange des résultats d’analyse statique (SARIF). BinSkim remplace l’ancien outil BinScope.

Pour plus d'informations sur BinSkim, consultez Utiliser BinSkim pour vérifier les binaires et le guide utilisateur de BinSkim .

Vérifier le code avec les tests du programme de compatibilité matérielle

élément de liste de contrôle de sécurité n° 17 :Utiliser les tests du programme de compatibilité matérielle associés à la sécurité pour vérifier les problèmes de sécurité.

Le programme de compatibilité matérielle inclut des tests liés à la sécurité peuvent être utilisés pour rechercher des vulnérabilités de code. Le programme de compatibilité matérielle Windows tire parti des tests du Kit de laboratoire matériel Windows (HLK). Les tests de fondamentaux des appareils HLK peuvent être utilisés en ligne de commande pour exercer le code du pilote et rechercher des faiblesses. Pour obtenir des informations générales sur les tests de base de l’appareil et le programme de compatibilité matérielle, consultez Kit de laboratoire matériel Windows.

Les tests suivants sont des exemples de tests qui peuvent être utiles pour vérifier le code du pilote pour certains comportements associés aux vulnérabilités du code :

DF - Test IOCTL aléatoire fuzz (Fiabilité)

DF - Test Fuzz sous-ouverture (Fiabilité)

DF - Test FSCTL de la mémoire tampon de longueur nulle Fuzz (Fiabilité)

DF - Test FSCTL aléatoire fuzz (Fiabilité)

DF - Test d’API Fuzz Misc (Fiabilité)

Vous pouvez également utiliser le délai de synchronisation du noyau inclus avec Driver Verifier.

Les tests CHAOS (Matériel simultané et système d’exploitation) exécutent simultanément différents tests de pilotes PnP, tests fuzz de pilote de périphérique et tests de système d’alimentation simultanément. Pour plus d’informations, consultez Les Tests CHAOS (Principes de base de l’appareil).

Les tests de pénétration des principes de base de l’appareil effectuent différentes formes d’attaques d’entrée, qui sont un composant essentiel des tests de sécurité. Les tests d’attaque et d’intrusion peuvent aider à identifier les vulnérabilités dans les interfaces logicielles. Pour plus d’informations, consultez Les Tests de pénétration (Principes de base de l’appareil).

Utilisez l'Device Guard - Test de conformité, ainsi que les autres outils décrits dans cet article, pour vérifier que votre pilote est compatible avec HVCI.

Outils de test personnalisés et spécifiques au domaine

Envisagez le développement de tests de sécurité personnalisés spécifiques au domaine. Pour développer des tests supplémentaires, rassemblez des commentaires des concepteurs originaux du logiciel, ainsi que des ressources de développement sans lien avec le type spécifique de pilote en cours de développement, et une ou plusieurs personnes familiarisées avec l’analyse et la prévention des intrusions de sécurité.

Comprendre comment les pilotes sont signalés à l’aide du Centre de création de rapports de pilotes vulnérables et malveillants Microsoft

Élément de liste de contrôle de sécurité #18 : Comprendre comment les pilotes sont signalés avec le Centre de rapport des pilotes vulnérables et malveillants Microsoft

Tout le monde peut soumettre un pilote questionnable à l’aide du Centre de création de rapports de pilotes vulnérables et malveillants Microsoft. Reportez-vous à cette entrée de blog pour plus d’informations sur la façon dont les pilotes sont soumis à des fins d’analyse : Améliorer la sécurité du noyau avec le nouveau Centre de rapports de pilotes vulnérables et malveillants Microsoft

Le Centre de rapports peut analyser et examiner les pilotes Windows créés pour les architectures x86 et x64. Les pilotes vulnérables et malveillants scannés sont signalés pour analyse et investigation par l’équipe des pilotes vulnérables de Microsoft. Une fois les pilotes vulnérables confirmés, une notification appropriée se produit, elles sont ajoutées à la liste de blocage des pilotes vulnérables. Pour plus d’informations sur cela, consultez les règles de bloc de pilotes recommandées par Microsoft. Ces règles sont appliquées par défaut aux appareils compatibles avec l’intégrité du code protégé par Hyperviseur (HVCI) et Windows 10 en mode S.

Passer en revue les ressources de codage sécurisées

élément de liste de contrôle de sécurité n° 19 :Passez en revue ces ressources pour approfondir votre compréhension des meilleures pratiques de codage sécurisées applicables aux développeurs de pilotes.

Instructions de codage du pilote en mode noyau sécurisé

création de pilotes Kernel-Mode fiables

Organisations de codage sécurisées

Carnegie Mellon University SEI CERT

Carnegie Mellon University SEI CERT C Coding Standard : Règles pour développer des systèmes sûrs, fiables et sécurisés (Édition 2016).

MITRE - Faiblesses abordées par le standard de codage sécurisé CERT C

Building Security In Maturity Model (BSIMM) - https://www.bsimm.com/

SAFECode - https://safecode.org/

Ressources CISA

OSR

OSR fournit des services de formation et de conseil au développement de pilotes. Ces articles de la newsletter OSR mettent en évidence les problèmes de sécurité des pilotes.

Noms, descripteurs de sécurité et classes d’appareil - Rendre les objets d’appareil accessibles... et SAFE

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

Locking Down Drivers - A Survey of Techniques

Meltdown et Spectre : Qu’en est-il des pilotes ?

Étude de cas

De l’alerte à la vulnérabilité du pilote : l’enquête Microsoft Defender ATP déterre les failles d’escalade de privilèges

Livres

24 péchés mortels de sécurité logicielle : failles de programmation et comment les corriger par Michael Howard, David LeBlanc et John Viega

L’art de l’évaluation de la sécurité logicielle : identification et prévention des vulnérabilités logicielles, Mark Dowd, John McDonald et Justin Schuh

Writing Secure Software Second Edition, Michael Howard et David LeBlanc

l’art de l’évaluation de la sécurité logicielle : identification et prévention des vulnérabilités logicielles, Mark Dowd et John McDonald

codage sécurisé en C et C++ (série SEI en ingénierie logicielle) 2e édition, Robert C. Seacord

programmation du modèle de pilote Microsoft Windows (2e édition), Walter Oney

Développement de pilotes avec windows Driver Foundation (référence développeur), Penny Orwick et Guy Smith

Formation

La formation en classe des pilotes Windows est disponible auprès des fournisseurs tels que les suivants :

La formation en ligne de codage sécurisé est disponible à partir de diverses sources. Par exemple, ce cours est disponible sur Coursera :

Identifier les vulnérabilités de sécurité dans la programmation C/C++.

SAFECode offre également une formation gratuite :

SAFECode.org/training

Certification professionnelle

CERT offre une certification professionnelle de codage sécurisé .

Résumé des points clés à prendre

La sécurité des pilotes est une entreprise complexe contenant de nombreux éléments, mais voici quelques points clés à prendre en compte :

  • Les pilotes résident dans le noyau Windows, et rencontrer un problème lors de l'exécution dans le noyau expose l'ensemble du système d'exploitation. En raison de cela, portez une attention particulière à la sécurité des pilotes et concevez en tenant compte de la sécurité.

  • Appliquez le principe du privilège minimum :

    a. Utiliser une chaîne SDDL stricte pour restreindre l’accès au pilote

    b. Restreignez davantage les IOCTL individuels.

  • Créez un modèle de menace pour identifier les vecteurs d’attaque et déterminez si tout peut être restreint.

  • Soyez prudent avec les pointeurs intégrés provenant du mode utilisateur. Ils doivent être sondés, accédés dans un bloc try except, et ils sont sujets aux problèmes de vérification d’état (ToCToU) à moins que la valeur du buffer ne soit capturée et comparée.

  • Si vous n’êtes pas sûr, utilisez METHOD_BUFFERED comme méthode de mise en mémoire tampon IOCTL.

  • Utilisez les utilitaires d’analyse du code pour rechercher les vulnérabilités de code connues et corriger les problèmes identifiés.

  • Recherchez des réviseurs de code compétents pour rechercher des problèmes que vous avez peut-être manqués.

  • Utilisez des vérificateurs de pilotes et testez votre pilote avec de multiples entrées, y compris les cas limites.