Notre contribution à la communauté de la sécurité de l'information et des systèmes d'information

Meltdown et Spectre - CERT - CONIX

Meltdown et Spectre : 1 mois après

Le CERT- CONIX a été beaucoup sollicité concernant la meilleure façon d’adresser les dernières vulnérabilités médiatisées : Meltdown et Spectre.

Étant donné la nature de ces vulnérabilités, qui affectent la plupart des fondeurs de processeurs, affectant donc la plupart des intégrateurs OEM et tous les systèmes d’exploitation, la réponse n’est pas simple et implique de coordonner tous ces acteurs. Malgré la notification initiale précoce aux fondeurs, et la longue période d’embargo, la plupart des éditeurs semblent pris de cours en ce qui concerne la publication des patchs pouvant adresser ces vulnérabilités.

Le but de cet article n’est pas de revenir en détail sur ces vulnérabilités ni leur fonctionnement. De nombreux billets existent pour cela. Le but ici est de faire un état des lieux de la situation un mois après la publication des vulnérabilités. Nous espérons ainsi aider les organisations à mettre en œuvre des plans d’actions pour remédier à ces vulnérabilités.

Revue des vulnérabilités et de leurs correctifs possibles

Exécution spéculative

Spectre et Meltdown reposent sur le fait que les effets de l’exécution spéculative ne sont pas observables du point de vue architectural (effets sur les registres, etc.). Néanmoins, elles sont observables au niveau micro-architectural (effets sur le cache).

De manière très simplifiée : l’exécution spéculative est la capacité d’un processeur à exécuter en avance certaines instructions sans être sûr que celles-ci seront nécessaires (par exemple lors d’un test plus ou moins long). Ceci permet de gagner du temps en exécutant en avance certaines parties de code dans le cas où le test valide. S’il ne valide pas, les instructions seront simplement  exécutées pour rien en avance. Ce qui n’engendre pas de perte de temps pour le processeur. Les capacités d’exécution spéculative des processeurs se chargent de mettre les registres en ordre à la fin du cycle d’exécution spéculative. C’est pour cela que les effets ne sont pas visibles au niveau architectural.

Ces vulnérabilités suivantes se basent sur le fait que les effets soient quant à eux visibles sur le cache (i.e. au niveau micro-architectural) du processeur et que des attaques par canaux cachés permettent de révéler ces informations. Étant donné le type d’exploitation, les bandes passantes possibles sont relativement faibles (environ 500ko pour Meltdown et environ 10Ko pour Spectre).

Les processeurs utilisant ces fonctionnalités d’exécution spéculative sont nombreux et sont sur le marché depuis longtemps. Il y a fort à parier que le processeur que vous utilisez pour lire cet article soit concerné et donc vulnérable (sauf dans le cas où vous utilisez un processeur SPARC).

Deux types de solutions existent pour rendre ces vulnérabilités inopérantes :

  • empêcher l’exécution spéculative dans les cas dangereux (ceci affecte les performances)
  • priver l’accès aux informations sensibles pour éviter les fuites (ceci affecte aussi potentiellement les performances)

Spectre variante 1 : LFENCE

La première vulnérabilité, ou “bounds-check bypass”, ou CVE-2017-5753 est la vulnérabilité la plus complexe des trois en terme de protection. Elle affecte la majorité des processeurs (Intel, AMD, ARM, …).

Cette vulnérabilité introduit une nouvelle classe de bugs qui exploite l’exécution spéculative du CPU et les effets de caches pour révéler des informations qui ne devraient pas être accessibles.

Afin de s’en protéger, il faut faire en sorte que certaines portions de code ne puissent pas être utilisées comme gadgets d’exécution spéculative. Le code doit donc être modifié. Diverses pistes peuvent être employées pour cela, qui sont détaillées plus bas.

Plusieurs approches permettent cela, soit demander aux auteurs d’applications d’inclure des macros faisant office de barrières aux endroits nécessaires, soit modifier les compilateurs pour qu’ils détectent tous seuls ces endroits et incluent les protections adéquates. La dernière solution est plus pertinente car elle ne demande pas de connaissance particulière aux programmeurs.  De plus, elle permet également de protéger du vieux code grâce à une simple re-compilation. Une re-compilation générale de l’OS et des logiciels est néanmoins nécessaire, ce qui entraine des mises à jour volumineuses.

 

Spectre variante 2 : IBRS et retpoline

La seconde vulnérabilité, “branch target injection” ou CVE-2017-5715, affecte elle aussi la majorité des processeurs.

Elle vise à empoisonner le prédicteur de branche du CPU pour rediriger l’exécution sur du code choisi par l’attaquant grâce à l’exécution spéculative.

Diverses approches existent également pour corriger ce problème. La première approche, développée par Intel, est de se baser sur une fonctionnalité de certains CPU, qui s’appelle IBRS (Indirect Branch Restricted Speculation) depuis le noyau. Elle protège tout le système d’un coup sans modification autre qu’au niveau du noyau. Cette protection nécessite une mise à jour de microcode des processeurs pour être effective. La qualité technique de cette approche a été vivement critiquée comme n’étant pas pérenne et affectant les performances.

Afin d’appliquer cette protection il faut :

  • avoir un microcode à jour
  • avoir un noyau supportant l’IBRS

L’autre approche, issue de travaux de Google, est d’utiliser des retpoline (ou return trampoline). L’objectif est d’empêcher l’exécution spéculative en utilisant une technique proche du ROP (return oriented programming). Cette technique est habituellement utilisée par les concepteurs d’exploits. Les retpolines se basent sur une faiblesse dans l’exécution spéculative qui fait que les processeurs ne peuvent spéculer face à un retpoline.

Cette technique nécessite également des modifications dans le code machine. L’approche prise est d’intégrer ces modifications dans les compilateurs afin qu’ils détectent les endroits où les retpolines sont nécessaires. Afin de protéger totalement un système, il faut le recompiler ainsi que tous ses logiciels. Ce qui demande des mises à jour très volumineuses.

Afin d’appliquer cette protection il faut :

  • utiliser un kernel compilé avec support des retpolines

L’approche retpoline souffre tout de même d’une faiblesse, les processeurs les plus récents (génération Skylake et postérieurs, sortis en 2015) sont capable de spéculer dans ces conditions, ce qui rend le retpoline inopérant.

 

Meltdown : KPTI

La troisième vulnérabilité, “rogue data cache load” ou CVE-2017-5754, affecte quant à elle tous les processeurs exceptés ceux du constructeur AMD.

Elle permet à un applicatif d’accéder aux données du noyau, chose qui n’est pas censée être possible.

La protection mise en place par Microsoft et Linux avait déjà été prototypée (bien que non intégrée) dans certains noyaux sous la forme de KAISER, ce qui a facilité le travail. En résumé, il s’agit simplement de séparer totalement les espaces d’adressage noyau et userland. Ceci empêche en effet les logiciels classiques de récupérer des informations telles que des adresses mémoires en espace noyau.

Cette technique appelée KPTI a pour bénéfice de durcir durablement les noyaux contre les attaques par canaux-cachés en général au prix d’une perte de performance non négligeable.

Le noyau est le seul élément à mettre à jour pour se protéger de cette vulnérabilité.

 

Bilan

La table ci-dessous récapitule à quel niveau les protections sont possibles pour telle ou telle vulnérabilité :

Vulnérabilité Spectre v1 Spectre v2 Meltdown
Contournement Compilateur Noyau et/ou Compilateur Noyau

La plupart de ces contournements ont des effets négatifs sur les performances, parfois de plusieurs pourcents. Ceci est provoqué par le fait que les processeurs exposent de fait des comportements qui n’étaient pas prévus (et donc non-documentés) et les développeurs doivent implémenter des protections contre ces comportements.

État des corrections

Microcode, BIOS et autres firmwares

Comme vu précédemment, la correction de la vulnérabilité Spectre v2 nécessite de mettre à jour le microcode des processeurs. Le microcode (ou firmware processeur) est une partie logicielle du processeur chargée au démarrage de celui-ci, qui permet d’implémenter des instructions complexes ainsi que de désactiver d’éventuelles fonctionnalités problématiques.

Le microcode est donc la façon dont les fondeurs mettent à jour leurs processeur. Cette mise à jour n’est pas persistante (au démarrage, le processeur utilise son microcode d’usine) et nécessite d’être ré-appliquée à chaque démarrage.

Le microcode peut être mis à jour de diverses manières :

  • par le BIOS ou UEFI
  • chargé par le noyau du système d’exploitation ou par le chargeur d’amorçage

La dernière option est la plus flexible. Elle permet également de protéger des systèmes n’ayant plus de mises à jour BIOS. De fait, mettre à jour un système d’exploitation via son système de mise à jour permettra de mettre à jour le microcode du processeur.

x86 : Intel & AMD

Intel a publié le microcode pour corriger le problème le 3 janvier. Cette version du microcode a vite été intégrée dans Windows Update ainsi que dans les distributions Linux. Ce qui a permis de diffuser le microcode rapidement. Malheureusement ce microcode provoquait des reboot intempestifs . Il a dû être désactivé en attendant une solution n’ayant pas d’effets de bords. La date de sortie de la seconde version du microcode Intel corrigeant le problème n’est pas connue à l’heure actuelle.

Intel prévoit de vendre ses futurs processeurs intégrant des protections matérielles contre ces vulnérabilités. Cependant nous ne savons pas encore quand ces processeurs arriveront sur le marché.

AMD a aussi publié un microcode corrigé pour ses processeurs. Ce microcode est, de la même façon, fourni par les systèmes de mises à jour des systèmes d’exploitation.

ARM

Les fondeurs ARM sont nombreux et apportent tous des modifications dans le design de leurs puces. Ce qui entraine une complexité dans le traçage des mises à jour. Certains n’utilisent pas de microcode sous cette forme-là, et donc ne peuvent être mis à jour. Nous vous conseillons dans ce cas de vous rapprocher du support du fabricant afin d’obtenir plus d’infos.

 

Compilateurs

GCC

A cette date, GCC 7.3 intègre le support du retpoline sur les architectures x86 et power. Ce support permet de compiler un noyau ou des drivers noyau en éliminant le risque de la variante 2 de Spectre. Les flags permettant d’activer ce support sont -mindirect-branch=thunk, -mfunction-return=thunk et -mindirect-branch-register.

A cette heure, GCC n’inclut pas encore de contre-mesure pour Spectre v1.

LLVM

Un travail est également en cours côté LLVM pour implémenter le retpoline via le flag -mretpoline qui sera inclut dans une future version. Les drivers et noyau pourront être compilés via ce seul flag, tandis que les exécutables dynamiques nécessitent l’ajout de -z retpolineplt et -z now.

LLVM n’inclut pas encore de contre-mesure pour Spectre v1 pour l’instant.

MSVC

Pour les architectures le permettant, MSVC protège le code en utilisant des instructions assembleur faisant office de barrière de spéculation. Concernant x86, c’est l’instruction LFENCE ; pour le monde ARM, 3 instructions différentes selon les familles : conditional move (ARM) ou conditional selection instruction (AArch64) ou enfin CSDB pour les autres.

Cette protection peut être mise en œuvre via le flag \Qspectre de MSVC. A l’heure actuelle, ce flag ne protège que le code de Spectre v1. Les futures mises à jour du compilateur amélioreront la couverture de ce flag.

Windows

Spectre variante 1

Windows Update a fourni en janvier les binaires recompilés avec les dernières avancées de MSVC (décrites plus haut) qui permettent de se protéger de Spectre v1. Ces mises à jour sont fournies sur tous les systèmes supportés par Microsoft à l’heure actuelle.

Spectre variante 2

L’approche prise par Microsoft pour se protéger de la variante 2 est de se baser sur l’IBRS. Ceci nécessite notamment un microcode à jour (fourni par Windows Update).

Ce travail est toujours en cours côté Microsoft. Il est à noter que Microsoft a envoyé un rollover Windows Update pour la mise à jour du microcode Intel qui provoquait des problèmes de stabilité avec quelques processeurs. Ceci ajoute du délai à la correction totale du problème pour les plateformes Windows.

Meltdown

Le noyau Windows est protégé de Meltdown depuis les mises à jour Windows Update de janvier 2018 pour toutes les versions de Windows supportées. Cette protection est basée sur le KPTI décrit plus haut.

Linux

Les versions de Linux actuellement protégées contre ces vulnérabilités sont les versions : 4.4, 4.9, 4.14 et 4.15.

Afin de savoir si vos systèmes sont protégés ou non, il est possible d’utiliser la commande suivante :

$ grep . /sys/devices/system/cpu/vulnerabilities/*
/sys/devices/system/cpu/vulnerabilities/meltdown:Mitigation: PTI
/sys/devices/system/cpu/vulnerabilities/spectre_v1:Vulnerable
/sys/devices/system/cpu/vulnerabilities/spectre_v2:Vulnerable: Minimal generic ASM retpoline

Dans le cas où la commande échoue, cela signifie que votre système n’inclut pas tous les patchs de protection contre Spectre et Meltdown. La solution la plus raisonnable est alors d’attendre que ces patchs soient intégrés par votre distribution.

Spectre variante 1

La variante 1 de spectre n’est actuellement pas adressée par Linux.

Spectre variante 2

La solution retenue pour le moment comme contre mesure contre Spectre v2 est basée sur les retpolines. La solution basée sur l’IBRS semblant repoussée.

Les retpolines sont actuellement implémentés dans les versions de Linux indiquées plus haut, il faut également que le noyau ait été compilé avec un compilateur supportant cette technique (uniquement GCC en stable à l’heure actuelle). La commande présentée ci-dessus donne un résultat (spectre_v2:Vulnerable: Minimal generic ASM retpoline) d’un noyau supportant les retpolines mais compilé avec une ancienne version de GCC. Dans le cas où cette commande retourne spectre_v2:Mitigation: Full generic retpoline, le noyau est à l’état de l’art des protections du monde Linux contre Spectre v2.

Le travail pour intégrer l’IRBS est en cours et viendra protéger les systèmes utilisant des processeurs de génération Skylake et ultérieures (où les retpolines sont ineffectifs, voir ci-dessus).

Meltdown

Meltdown est corrigé dans Linux pour les versions 4.4, 4.9, 4.14 et 4.15 en architecture x86 (32 et 64 bits).

La protection mise en place par Linux est nommée KPTI (Kernel Page Table Isolation). Elle est dérivée d’un ancien patchset nommé KAISER. Il avait pour but de se protéger de ce type d’attaque par canaux cachés. Bien qu’à l’époque de conception de ce dernier aucune attaque de ce type n’avait été démontrée possible.

 

Android

Google a contourné ces vulnérabilités en limitant la précision temporelle de certaines API. Ceci permettant de rendre l’exploitation de Spectre et Meltdown fastidieuse et imprécise. Ces limitations (qui ne sont pas des vraies corrections de ces failles) ont été fournies dans le cadre de Android 2018-01-05 Security Patch Level. Vérifiez auprès de votre constructeur la disponibilité de ces patchs. Des corrections plus complètes sont encore à venir.

Concernant Meltdown : pour les processeurs ARM, des corrections similaires à celles de Linux en x86 seront probablement incorporées dans Linux pour la version 4.16. Afin de bénéficier de correctifs, il est préférable de s’orienter vers les arbres de développement de Android. Ceux-ci intègrent d’ores et déjà des patchs pour les versions 3.9, 4.4 et 4.9.

Certaines de ces vulnérabilités peuvent être exploitées depuis une page web. La question de la protection des navigateurs web se pose alors.

Les principaux navigateurs web sont donc en train d’intégrer des protections. Ceci afin de limiter la précision des API qui pourraient permettre à des pages web d’exploiter ces vulnérabilités. Firefox, Chrome et IE/Edge ont d’ores et déjà désactivé la fonction Javascript SharedArrayBuffer sur leurs dernières versions afin d’empêcher des pages web malveillantes de créer des timers de haute précision permettant d’exploiter ces vulnérabilités. D’autres modification ont eu lieu sur certains navigateurs pour limiter la précision de certaines API qui pourraient permettre d’exploiter ces vulnérabilités.

Les navigateurs implémenteront dans le futur des contre-mesures contre ces vulnérabilités dès qu’elles seront disponibles de manière globale pour les applicatifs.

Conclusion

Ces vulnérabilités sont complexes. Certaines solutions n’ont pas encore vu le jour de manière fiable. L’industrie ayant été prise de cours, les solutions mises en œuvre (parfois très complexes comme le KPTI) ont clairement été développées afin de répondre rapidement aux vulnérabilités et parfois au dépend de la qualité (citons en exemple les incompatibilités avec les antivirus, les problèmes de microcode Intel, les bugs de Ubuntu, etc.).

Tous les problèmes ne sont pas résolus, loin de là, voici l’état actuel par système d’exploitation :

OS Spectre v1 Spectre v2 Meltdown
Windows Protégé En cours Protégé
Linux Vulnérable Noyau Protégé, applicatifs vulnérables Protégé
BSD Vulnérable Vulnérable Vulnérable

La question de la protection des applicatifs est toujours ouverte également.

Ces bugs seront présents dans les processeurs pour de nombreuses années. Il est nécessaire de souligner l’importance des mises à jour systèmes et applicatives qui corrigent ces vulnérabilités. La plupart des correctifs sont intrusifs et ont été publiés rapidement. Ils ont des effets non négligeables sur les performances et parfois la stabilité des systèmes. Dans les mois, les mises à jour seront également très importantes afin de regagner partiellement les performances perdues (des travaux sont déjà en cours sur ces points) et de corriger des bugs d’implémentation qui ne manqueront pas d’arriver.

Il est également important de noter que ces vulnérabilités ouvrent une nouvelle classe de vulnérabilités et que le concept d’exécution spéculative n’a été utilisé dans aucun exploit connu dans des attaques à l’heure actuelle.

By | 2018-02-01T11:42:41+00:00 01/02/2018|Non classé|