Vulnérabilité des firmwares et leurs contre-mesures

Dans les systèmes électroniques et informatiques, un micrologiciel (firmware en anglais) est considéré comme étant l'association de code exécutable et des données stockées à l'intérieur. Un logiciel embarqué est un logiciel réalisé pour contrôles des périphériques ou appareils, qui ne sont généralement pas considérés comme étant des ordinateurs à part entière. Ils sont particulièrement utilisés au sein de matériels fonctionnant avec de hautes contraintes temps et mémoire. Cet article décrit les vulnérabilités des micrologiciels et leurs contre-mesures.

Introduction aux micrologiciels modifier

La vulnérabilité des micrologiciels est une problématique ascendante et évolutive liée à la sécurité des systèmes embarqués et informatiques en général. Ces vulnérabilités sont exploitables et peuvent en l’absence de tout correctif (Mise à jour) être la voie d’attaque des systèmes embarquant des micrologiciels. Plusieurs innovations technologiques issues du domaine de la recherche ont permis des progrès dans la sécurité des micrologiciels. Ces contremesures bien que fiables ne sont dans certains cas pas perennes à cause de la technologie et des failles qui sont évolutives.

Définitions modifier

Une vulnérabilité se réfère à toute chose qui par ses insuffisances, ses imperfections, peut donner prise à des attaques[1]. La notion de vulnérabilité peut être également perçue comme un ensemble de sensibilités d'un dispositif aux blessures, aux attaques ou son incapacité (difficulté) à se maintenir fonctionnel face à sa mise en péril par autrui [2].

Un micrologiciel, aussi appelé “firmware”, microprogramme et même logiciel embarqué, est intégré dans des systèmes matériels. Les micrologiciels sont davantage présents dans la plupart des équipements que nous utilisons, ordinateurs, voitures, portables, imprimantes, réfrigérateurs. Il existe plusieurs types de micrologiciels. Ce sont des programmes en mémoire et en lecture seule[3].

La vulnérabilité des micrologiciels nous renvoie sur la vulnérabilité de tout système informatique. Celle-ci est spécifique à l’ensemble des failles et bugs que contiennent les micrologiciels en l’absence de tout correctif et qui peuvent malencontreusement être exploitées pour des attaques. Les micrologiciels des systèmes autonomes ou non peuvent donc être sujet à de nombreuses attaques dues à de nombreuses failles. On met l’accent ici sur toutes les éventuelles failles connues ou non et qui sont exploitables dans le but de contrôler, rendre vulnérable, ou mettre en péril le bon fonctionnement du système[4].

Problématique de la vulnérabilité d’un micrologiciel modifier

La problématique de la sécurité n’est pas spécifique aux systèmes informatiques usuels destinés aux utilisateurs finaux, mais à l'ensemble des systèmes informatiques embarqués qui aujourd’hui font face à de nombreux défis en matière de sécurité. Un micrologiciel est généralement un microprogramme informatique spécifique et codé dans un langage de données. Il est connu que certaines erreurs de programmations dans certains langages se révèlent être la source de nombreuses vulnérabilités, donc point de départ des attaques. Cette assertion n’épargne pas les micrologiciels, même s’ils sont dans des systèmes embarqués [5]. De manière intrinsèque, les micrologiciels sont donc susceptibles de présenter les erreurs de programmations (vulnérabilités) qui peuvent être sources d’attaques.

Bien qu'il soit possible de désosser le micrologiciel, de supprimer certaines limitations, ces types d’attaques nécessitent de considérables efforts à mettre en œuvre. Plusieurs mécanismes alternatifs pour contourner les limitations imposées par l'interface du micrologiciel sont connus. Pour comprendre notre approche, il est d'abord nécessaire de comprendre son architecture. L’exemple ci-dessous nous présente un micrologiciel 802.11[6].

 

Ces dernières années, plusieurs chercheurs ont examiné la sécurité des micrologiciels ainsi que divers dispositifs, tels que les bandes de base, cartes, chipsets[6], etc. Les vulnérabilités dans ces composants embarquant les micrologiciels sont sujets à des attaques qui pourraient permettre à un intrus de prendre le contrôle total de la composante et l'utiliser comme un tremplin pour lancer d'autres attaques contre d'autres systèmes d'exploitation ou d'autres périphériques[7].

Architecture et caractéristiques, diversité des micrologiciels modifier

Plusieurs architectures sont connues en fonction du champ d’application du micrologiciel, en partant des ordinateurs ou des équipements de grande utilité[8], mais aussi en fonction du type de micrologiciel. Les différentes architectures de micrologiciels sont basées sur des bus entrées-sorties. Il est donc opportun de préciser qu’il n’existe pas d’architecture standard ni de modèle figé d’architecture pour les micrologiciels.

Les micrologiciels, comme l’ensemble des systèmes à mémoire se caractérisent généralement par la taille mémoire qui induit le temps de flashage, le flux de transfert et la méthode de mise à jour. Les micrologiciels peuvent être classés en deux grandes familles. Nous avons les type “binaire”: compressés ou non et de type archive [8].

 

Dans les systèmes embarqués, le micrologiciel est généralement organisé comme représenté sur la figure ci-dessus. Au cours du processus de démarrage, le chargeur de démarrage est maintenu, il peut être amorcé en premier lieu lorsque le système est sous tension et ensuite le noyau de l'OS suit de près.

Comme le bootloader fonctionne tout d'abord, il initialise le matériel nécessaire et prépare les environnements logiciels de fonctionnement. Dans les détails, le bootloader divise processus de chargement en deux parties. L’étape 1 est étroitement liée au matériel.

Dans l'espace restant, les programmes d'applications sont stockés et généralement organisés par le système de fichiers et la mémoire vive [6]. Avant de démarrer l'étape 2, il vérifie habituellement un premier code de 4 ko chargé par le matériel selon le processus de démarrage décrit.

Ensuite, l'étape 2 est chargée et démarrée. Cette étape permet de lancer les fonctions plus sophistiquées. Il initialise les différents besoins pour le matériel (ports, les entrées et les sorties). Il va ensuite charger et démarrer le noyau du système chargé de la gestion des ressources du système, tels que les différents processus, la gestion de la mémoire. Ainsi, le système est démarré et les programmes d'application peuvent fonctionner sur la base de ceux-ci: valeurs d'initialisation.

De toute évidence, cette architecture de micrologiciel est très fragile, parce qu'elle ne garantit pas la fiabilité de n'importe quelle étape des différents processus.

Intérêt et motivations des attaques de micrologiciels modifier

Les attaquants de micrologiciels, utilisent généralement les failles d’implémentation pour nuire au système. Même si c’est la première appréhension qu’on a du concept des attaques, il faut reconnaitre qu’ils permettent d’évaluer, la sécurité et la robustesse des systèmes embarqués. Bien que la finalité d’une attaque soit de mettre hors d’état de service le système embarquant le micrologiciel, il faudrait sous un autre angle voir des intérêts économiques, stratégiques et même politique.

Exemples d’attaques sur architecture x86 modifier

System Management Mode modifier

Description modifier

Le SMM (System Management Mode) est le mode d’exécution des processeurs x86 et x64 le plus privilégié. Lorsque le processeur est dans ce mode, l’exécution normale du CPU est suspendue pour laisser la main généralement à un micrologiciel ou à un débogueur matériel. Le SMM est un mode 16-bit qui est utilisé pour des applications telles que la gestion de la température ou de l'énergie (ex. : ACPI). Il est possible d'entrer dans ce mode uniquement lors de la réception d'une SMI (générées par le Northbridge ou lors de l'écriture du registre AMPC). Une zone mémoire spéciale appelée SMRAM permet de sauvegarder le contexte du CPU lors du basculement dans le SMM. À la réception d'une SMI, et donc au moment du basculement en SMM, un handler SMI sera exécuté depuis la SMRAM. La SMRAM est située dans la RAM mais n'est pas accessible par le CPU en raison du verrou D_OPEN du chipset. Ainsi, même en ring0, le CPU ne peut pas constater l'existence des handlers SMI ou même remarquer l'interruption de l'exécution normale du CPU.

Protections de la SMRAM modifier

Le code exécuté en SMM ayant encore plus de privilèges que le mode ring0, il est nécessaire de le protéger. La position de la SMRAM est indiquée par le registre SMBASE qui ne peut être accédé qu'en SMM. La SMRAM ne peut être accédée depuis les autres modes CPU sauf si le verrou D_OPEN est ouvert. Pour empêcher la modification du code des handlers de SMI, il existe également un verrou D_LCK qui met la SMRAM en lecture seule.

Contournement du verrou D_LCK modifier

Afin de permettre la corruption de la SMRAM malgré le verrou D_LCK, certaines recherches ont illustré des techniques de contournement de ce verrou. Par exemple, il existe des techniques d'empoisonnement de cache [9] ou d'attaque de l'ouverture graphique (en) du chipset AGP [10],[11]

Attaque via l'ouverture graphique modifier

Loïc Duflot [12],[13] a montré comment utiliser les mécanismes d'ouverture graphique pour contourner D_LCK. L'ouverture graphique d'AGP est une zone de l'espace des adresses physiques utilisée pour une communication rapide, via DMA, entre le contrôleur graphique (ex: serveur X) et le GPU. Étant donné qu'il est pas certain qu'on puisse avoir une zone contigüe de mémoire physique disponible pour cette ouverture graphique, un mécanisme de traduction d'adresse existe au sein du chipset (à ne pas confondre avec la MMU[Quoi ?] qui se situe entre le CPU et le northbridge). Grâce à ce mécanisme, il est possible d'avoir l'impression qu'une zone de l'espace physique est disponible. Le problème montré est qu'il est possible, depuis une application utilisateur disposant des privilèges d'entrées-sorties, de modifier les registres de configuration de l'ouverture graphique. Ceux-ci permettent notamment de positionner de manière arbitraire l'ouverture et de spécifier l'adresse de la table de traduction. Ainsi, on pourra positionner l'ouverture graphique sur une zone critique d'une noyau (ex: GDT[14]) pour la rediriger vers une partie de la mémoire physique correspondant à de la mémoire que l'on contrôle.

Attaque par empoisonnement du cache CPU modifier
SMRAM et mise en cache modifier

Sur plateforme x86, il existe des registres spéciaux appelés MSR. Certains de ces MSR sont les MTRRs. Les MTRRs fixes permettent d'indiquer la stratégie de cache (write-back, write-through etc) de certaines zones mémoire "legacy". Les MTRRs variable permettent de spécifier la stratégie de cache d'une zone de mémoire physique arbitraire. Si on configure un MTRR variable pour indiquer une stratégie de cache en write-back pour la zone SMRAM, l'exécution dun handler SMI va alors copier cette zone dans le cache. Si à la fin de son exécution, le cache n'est pas nettoyé, lorsque le système d'exploitation reprendra la main, une partie de la SMRAM sera toujours présente dans le cache. Ainsi, la version cachée du handler SMI sera accessible en mode protégé malgré D_LCK. Ce cache est un cache de données. Ainsi, modifier la version du handler SMI présente dans ce cache ne devrait pas avoir d'effet car la version correcte serait présente dans le cache d'instruction. Cependant, lors de la transition entre le mode protégé (32 bits, ou 64 bits pour le mode long (en)) va invalider le cache d'instructions et le recharger grâce aux données présentes dans le cache de données. C'est pourquoi la modification du code du handler SMI présent dans le cache de données va permettre de contourner de manière fiable le verrou D_LCK et de prendre le contrôle de la SMRAM depuis le mode protégé.

Attaque des mécanismes de mise à jour modifier

Plusieurs attaques contre des micrologiciels tels que BIOS ou UEFI ont été démontrées. Récemment, une attaque d’une implémentation d’UEFI[15] a été démontrée à la conférence BlackHat USA. Celle-ci permet une escalade de privilèges en tirant profit du mécanisme de mise à jour du micrologiciel. Généralement, après la compromission d’un processus utilisateur d’une machine, un scénario de post-exploitation classique commence à essayer de prendre le contrôle de l’espace noyau afin d’installer un rootkit. Cependant, c’est rendu difficile en raison de certaines protections. Par exemple, les systèmes d’exploitation Windows exigent que tout code exécuté en espace noyau soit signé. Par ailleurs, PatchGuard [16] vérifie à intervalles réguliers l’intégrité du noyau. Cependant, il existe d’autres options. Si l’attaquant ne souhaite pas corrompre le noyau, il peut essayer de compromettre l’amorceur (MBR), la SMRAM ou encore l’UEFI. Comme le montre le schéma suivant, il existe des techniques de mitigation des attaques de chacun de ces composants.

Ainsi, les auteurs de l'Extreme Privilege Escalation on Windows 8 UEFI[15] proposent d’étudier l’implémentation de UEFI pour non pas réécrire le micrologiciel mais pour exploiter une vulnérabilité auprès du micrologiciel légitime. Windows 8 a introduit une API qui permet à un processus utilisateur privilégié de s’interfacer avec une interface UEFI pour notamment modifier certaines variables d’environnement UEFI. Certaines vulnérabilités ont été co-découvertes par les équipes de MITRE et Intel qui utilisent les variables UEFI [17]. Une de ces variables contrôle l’adresse d’une « capsule » de mise à jour. Le système d’exploitation va alors fragmenter le contenu au sein de l’espace d’adressage.

Après un redémarrage spécial (“warm reset”), le code UEFI va, avant de vérifier la signature du nouveau micrologiciel, rassembler les morceaux fragmentés, parser l’enveloppe de la capsule de mise à jour puis parser certains contenus non signés de la capsule (ex: image de l’écran d’accueil). Le premier exploit de type “reflash de BIOS” a été présenté par Wojtczuk et Tereshkin et exploitait une vulnérabilité dans l’analyse syntaxique de l’image de l’écran d’accueil. Les auteurs de l'UEFI Privilege Escalation [15] ont dévoilé d’autres vulnérabilités telles qu’un dépassement d’entier lors de la vérification de la taille de la capsule, un dépassement d’entier lorsque la somme des longueurs des fragments est calculée ou encore un débordement arithmétique avant une allocation lors de l’analyse syntaxique d’une enveloppe. D’après leurs dires, les auteurs ont été capable de découvrir de nombreux débordement d’entiers simple à trouver en l’espace de seulement une semaine. Ils remarquent également que l’implémentation Edk2 est open source et critique mais ne semble pourtant pas avoir une bonne qualité de code.

Contre-mesures modifier

Vérification logicielle modifier

Analyse statique modifier

Théorie des interprétations abstraites modifier

La théorie des interprétations abstraites consiste à abstraire la sémantique d’un programme pour produire une sur-approximation complète (“sound”)[18]. De ce fait, la sémantique abstraite couvre l’ensemble des cas possibles (et plus). L’approximation doit être suffisamment grossière pour qu’elle devienne calculable. C’est ce qu’essaie de montrer les schémas suivant [19].

Cette théorie est notamment utilisée dans des projets tels que Astrée[20].

Exécution symbolique modifier
 
Représentation de l'exécution symbolique d'un code C.

Lors d’une exécution symbolique d’un programme, les variables correspondant à des entrées sont des valeurs symboliques. Cela signifie qu’une variable représente l’ensemble des valeurs qu’elle peut prendre et non une valeur précise. Le programme est ensuite exécutée avec un moteur d’exécution adapté. Pour chaque instruction, on modifie les contraintes des variables. À chaque branchement, à l’aide d’un solveur SAT, le moteur décide l’ensemble des instructions suivantes qu’il est possible d’exécuter. Ainsi, grâce à une exécution symbolique, à partir d’un état donné, on pourra connaitre l’ensemble des états qu’il est ensuite possible d’atteindre[21]. Un cours de la SEAS d'Harvard[22] explique le sujet assez bien.

Fuzzy testing modifier

Pour tester les logiciels, il existe des techniques de fuzzing consistant à générer de nombreux tests et monitorer les crash. Des frameworks tels que peach mettent à disposition des interfaces spéciales pour les micrologiciels[23]. On trouve également des fuzzers spécialisés dans le fuzzing de micrologiciels tels que Plashdance [24]. C'est un fuzzer de protocoles et de formats de fichiers qui se base sur des mutations de certains extraits de micrologiciels existants.

Exemples de contre-mesures pour plateforme x86 modifier

BIOS “chronomancy” modifier

Le système “BIOS chronomancy”[25] est un système défensif développé par une équipe de MITRE basée sur l’idée des “attestations temporelles” [26]. C’est une alternative à la notion de “Static Core Root of Trust for Measurement” (S-CRTM) des TPM (Trusted Platform Module) [27].

Copernicus modifier
Protections de la SMRAM modifier

DeepWatch [28] est un scanner d'intégrité qui permet notamment de monitorer la SMRAM. Une preuve de concept est implémentée dans le micrologiciel (G)MCH des chipsets Intel Q35. Il essaie aussi de détecter les rootkits utilisant VT-x.

Chipsec modifier

Chipsec est un projet lancé par Intel Security permettant d’améliorer la sécurité d’une plateforme. Il fut présenté à l’occasion sur CanSecWest 2014[29]. Par sécurité de la plateforme, on désigne deux situations distinctes. La première consiste à vérifier la configuration et l’implémentation du matériel. Ainsi, Chipsec s’assure que le matériel dispose de certaines fonctionnalités de sécurité et que celles-ci sont correctement configurées. La deuxième situation désignée par le terme “sécurité de la plateforme” désigne la configuration et l’implémentation des micrologiciels. On cherche alors à s’assurer que des contrôles d’accès aux interfaces des micrologiciels existent et que tous les verrous sont mis en place. Dans les deux cas, Chipsec essaie de démontrer que les mécanismes de sécurité des micrologiciels et du matériel sont présents et utilisés. Par exemple, pour prévenir les premières attaques sur la SMRAM présentée par Loïc Duflot[30], attaques sur le matériel donc, la plateforme vérifie que le verrou D_LOCK est bien activé. Un exemple concernant la sécurité des micrologiciels est la vérification de l’utilisation des registres de contrôle du BIOS et en particulier des verrous BLE et BIOSWE[31]. D’après Chipsec[29], la liste de vérifications de sécurité concernant les micrologiciels est la suivante :

Mécanisme Module Référence
Nettoyage du tampon clavier du BIOS bios_kdr_buffer DEFCON 16, 2008[32]
Protection en écriture du BIOS bios_wp CanSecWest 2013[33]
Verrou de l’interface BIOS bios_ts POC 2007[34]
Contrôle d’accès des clefs Secureboot secureboot.keys UEFI Specification[35]
Contrôle d’accès des variables Secureboot secureboot.variables UEFI Specification[35]
Verrou du contrôleur SPI spi_lock Copernicus[36]

Secure Boot modifier

Le Secure Boot est un mécanisme supporté par les micrologiciels UEFI, mis en place par Intel visant à signer les chargeurs d’amorçage des systèmes d’exploitation. Lors du démarrage du PC, le Secure Boot va vérifier la signature numérique de l’amorceur, à l’aide d’un catalogue de clés, avant de le charger. Ce dernier pourra alors démarrer le noyau du système concerné. Si la signature de l’amorceur est considérée comme invalide, l’UEFI refusera le démarrage[37].

Le principal intérêt de ce mécanisme est de se prémunir contre les modifications malveillantes des bootloader (“Bootkits”), car une telle modification entraînerait l’invalidation de la signature associée. À ce but, l’UEFI stocke un catalogue de clés autorisées, modifiable uniquement lors de l’installation du système ou par action manuelle dans le logiciel de configuration de l’UEFI (accès physique à la machine).

Ce catalogue est stocké généralement en NVRAM, inaccessible une fois le système démarré, ainsi que les paramètres du Secure Boot, ce qui permet également d’en empêcher la modification ou la désactivation par un logiciel malveillant. Ce mécanisme implique également d’amorcer l’ordinateur exclusivement par UEFI car il empêche de façon intrinsèque un démarrage classique (“Legacy Boot”).

TPM : Intel TXT modifier

Intel Trusted Execution Technology (Intel TXT) est un mécanisme permettant la mise à disposition d’une “racine” de confiance[27]. C’est un composant le plus petit possible, difficile à altérer ou contourner et qui permet de mesurer certains composants de la platforme au démarrage de la machine tels que le BIOS, le chargeur d’amorçage ou les gestionnaires de machines virtuelles (VMM). Pour cela, il existe un environnement de référence appelé “Measured Launch Environment” (MLE) qui permet de comparer certains éléments critiques avec cette référence. Il est intéressant que plusieurs attaques contre TXT ont déjà été présentées[38],[39],[23].

Notes et références modifier

  1. [1], Larousse
  2. [2], Jean-Claude Thouret, 1996, Pages 407-422
  3. [3], CURRY, Stephen M., FOX, Christopher W., et LOOMIS, Donald W, U.S. Patent No 6,105,013, 15 août 2000, p. 26
  4. [4], Global Security Mag, Kaspersky Lab, juillet 2011
  5. [5], Laurent Butti, France Télécom R&D Laboratoire Séecurité des Services et Réseaux, Actes du symposium SSTIC07, 2007 p2
  6. a b et c John Bellardo,12th USENIX Security Symposium, August 4–8, 2003, Washington, DC, USA, p. 3
  7. Loic Duflot, « Contribution à la sécurité des systèmes d’exploitation et des microprocesseurs »
  8. [6], Hongfei Yin, 2011 IEEE, p. 1190
  9. [7]
  10. [9]
  11. [10]
  12. [11]
  13. [12]
  14. a b et c [13], Extreme Privilege Escalation on Windows 8 UEFI
  15. [14], Kernel Patch Protection
  16. [15], UEFI Vulnerability
  17. [16], A gentle introduction to formal verification of computer systems by abstract interpretation
  18. [17], A very informal introduction to the principles of abstract interpretations
  19. [18], The Astrée Static Analyser
  20. [19], FIE on Firmware : Finding Vulnerabilities in Embedded Systems using Symbolic Execution
  21. [20], Symbolic Execution
  22. a et b [21]
  23. [22]
  24. [23], BIOS Chronomancy : Fixing the Core Root of Trust for Measurement
  25. [24], New Results for Timing-Based Attestation
  26. a et b [25], Intel Trusted Execution Technology
  27. [26]
  28. a et b [27], Platform Security Assessment
  29. [28], SMM 2006
  30. [29], Attacking Intel BIOS
  31. [30], DEFCON 16, 2008
  32. [31], CanSecWest 2013
  33. [32], PoC 2007
  34. a et b [33], UEFI 2.4 Specification, Errata B
  35. [34], Copernicus : Question Your Assumptions about BIOS Security
  36. [35], Secure Boot on Intel UEFI
  37. [36]
  38. [37]

Bibliographie modifier