### 2.1.8.1 Formalisation de la sémantique du jeu d'instruction

Les spécifications publiques des ISA des principales architectures disponibles sur le marché (x86, ARM) sont publiées sous forme d'une description textuelle informelle. Cette description est volumineuse, parfois ambiguë. La description précise de la sémantique de certains mécanismes peut être dispersée dans plusieurs ouvrages. Cet état de fait complexifie la mise au point et l'adoption de méthodes formelles pour la vérification des mécanismes de sécurité matériels.

Toutefois, des travaux récents ont proposé de formaliser la sémantique de l'ISA des processeurs. Ainsi, ARM a établi une spécification formelle exécutable de ses processeurs dans le but de réaliser des vérifications formelles par *model-checking* et du test [173]. ARM a appliqué cette approche à plusieurs de ces microprocesseurs [174]. Cette spécification formelle est disponible sur le site du constructeur [175].

Des travaux se sont également intéressés à la formalisation de l'ISA des processeurs x86 [176] mais seule la partie utilisateur est modélisée, ce qui représente tout de même un travail conséquent, étant donné la complexité de ce jeu d'instructions. Toutefois, cette limitation ne permet pas de vérifier les mécanismes de sécurité qui s'appuient sur les instructions privilégiées.

Le projet SAIL de l'université de Cambridge a développé un *framework* et un langage de spécification permettant de spécifier formellement différentes architectures et d'utiliser cette spécification formelle dans différents outils de test et de validation formelle [177]. Il permet également de générer automatiquement une description textuelle de l'architecture. Les auteurs ont pu appliquer ce *framework* pour modéliser formellement l'ISA des processeurs ARM (en collaboration avec le constructeur), RISC-V et CHERI. Le langage a été adopté officiellement par la fondation RISC-V pour la spécification formelle de l'architecture RISC-V.

Un des défis consiste à s'assurer que l'implémentation matérielle, qu'il s'agisse d'un circuit ASIC ou d'un *softcore* implémenté sur FPGA, respecte cette spécification formelle. Chlipala *et al.* [178] ont proposé le langage de description de matériel Kami, qui permet de concevoir des composants matériels (comme les langages VHDL ou Verilog), mais aussi de prouver (grâce au langage Coq) l'équivalence entre de tels composants. Chlipala *et al.* ont proposé, comme application de leur langage, une implémentation d'une partie d'un processeur RISC-V. Plus récemment, les auteurs de Kami ont proposé Kôika [179], un compilateur vérifié d'un HDL proche de Bluespec vers des circuits RTL.

L'entreprise SiFive<fnref n="10" />, qui propose notamment des implémentations FPGA de RISC-V, a repris la formalisation de Kami et une implémentation plus complète d'un processeur RISC-V, en Kami, est en cours de développement [180]. Toutefois, le projet ne semble plus actif.

### 2.1.8.2 Modélisation et preuve formelle de mécanismes de sécurité matériels

Letan *et al.* ont travaillé sur la formalisation de mécanismes de sécurité matériels, en étudiant notamment le SMM des processeurs x86 [181]. Une spécification formelle de ce mode d'exécution, ainsi qu'un modèle minimal de l'architecture x86, ont été écrits en Coq.

<footnote n="10">10. https://www.sifive.com/</footnote>
### 2.1.8.1 Formalisation de la sémantique du jeu d'instruction

Les spécifications publiques des ISA des principales architectures disponibles sur le marché (x86, ARM) sont publiées sous forme d'une description textuelle informelle. Cette description est volumineuse, parfois ambiguë. La description précise de la sémantique de certains mécanismes peut être dispersée dans plusieurs ouvrages. Cet état de fait complexifie la mise au point et l'adoption de méthodes formelles pour la vérification des mécanismes de sécurité matériels.

Toutefois, des travaux récents ont proposé de formaliser la sémantique de l'ISA des processeurs. Ainsi, ARM a établi une spécification formelle exécutable de ses processeurs dans le but de réaliser des vérifications formelles par *model-checking* et du test [173]. ARM a appliqué cette approche à plusieurs de ces microprocesseurs [174]. Cette spécification formelle est disponible sur le site du constructeur [175].

Des travaux se sont également intéressés à la formalisation de l'ISA des processeurs x86 [176] mais seule la partie utilisateur est modélisée, ce qui représente tout de même un travail conséquent, étant donné la complexité de ce jeu d'instructions. Toutefois, cette limitation ne permet pas de vérifier les mécanismes de sécurité qui s'appuient sur les instructions privilégiées.

Le projet SAIL de l'université de Cambridge a développé un *framework* et un langage de spécification permettant de spécifier formellement différentes architectures et d'utiliser cette spécification formelle dans différents outils de test et de validation formelle [177]. Il permet également de générer automatiquement une description textuelle de l'architecture. Les auteurs ont pu appliquer ce *framework* pour modéliser formellement l'ISA des processeurs ARM (en collaboration avec le constructeur), RISC-V et CHERI. Le langage a été adopté officiellement par la fondation RISC-V pour la spécification formelle de l'architecture RISC-V.

Un des défis consiste à s'assurer que l'implémentation matérielle, qu'il s'agisse d'un circuit ASIC ou d'un *softcore* implémenté sur FPGA, respecte cette spécification formelle. Chlipala *et al.* [178] ont proposé le langage de description de matériel Kami, qui permet de concevoir des composants matériels (comme les langages VHDL ou Verilog), mais aussi de prouver (grâce au langage Coq) l'équivalence entre de tels composants. Chlipala *et al.* ont proposé, comme application de leur langage, une implémentation d'une partie d'un processeur RISC-V. Plus récemment, les auteurs de Kami ont proposé Kôika [179], un compilateur vérifié d'un HDL proche de Bluespec vers des circuits RTL.

L'entreprise SiFive<fnref n="10" />, qui propose notamment des implémentations FPGA de RISC-V, a repris la formalisation de Kami et une implémentation plus complète d'un processeur RISC-V, en Kami, est en cours de développement [180]. Toutefois, le projet ne semble plus actif.

### 2.1.8.2 Modélisation et preuve formelle de mécanismes de sécurité matériels

Letan *et al.* ont travaillé sur la formalisation de mécanismes de sécurité matériels, en étudiant notamment le SMM des processeurs x86 [181]. Une spécification formelle de ce mode d'exécution, ainsi qu'un modèle minimal de l'architecture x86, ont été écrits en Coq.

<footnote n="10">10. https://www.sifive.com/</footnote>
Une preuve a ensuite été établie que cette spécification respecte une politique de sécurité formellement spécifiée, sous réserve que le BIOS utilise correctement ce mécanisme. Ce dernier point fait l'objet d'hypothèses qui expriment explicitement les contraintes d'utilisation du mécanisme que les développeurs du BIOS doivent respecter. Toutefois, le modèle du processeur utilisé n'est pas complet et la preuve porte uniquement sur la spécification.

Ferraiuolo et al. ont proposé un HDL (Hardware Description Language, langage de description du matériel) fortement typé permettant de spécifier et de prouver des mécanismes d'isolation en utilisant des techniques de vérification des flux d'information, à l'aide d'une analyse statique de vérification du typage [182]. Ils ont appliqué leur approche en implémentant un mécanisme similaire à TrustZone sur un softcore MIPS. Des chercheurs ont proposé une approche similaire en s'appuyant sur Chisel, un HDL de haut niveau utilisé notamment pour implémenter des processeurs RISC-V [183]. Ils vérifient que la politique de flux d'information est respectée à l'aide d'un solveur SMT (Satisfiability Modulo Theories).

Récemment, les chercheurs impliqués dans les projet CHERI et SAIL ont utilisé le langage SAIL pour spécifier l'architecture CHERI et prouver qu'elle garantit certaines propriétés de sécurité, notamment l'évolution monotone des capacités (un attaquant ne peut faire évoluer une capacité pour la rendre plus permissive) [184]. SAIL peut également être utilisé pour tester une implémentation afin de s'assurer qu'elle est conforme à la spécification. Le projet ne permet cependant pas, à l'heure actuelle, de vérifier formellement qu'une implémentation respecte la sémantique de la spécification formelle.

## 2.2 Attaques logicielles contre la microarchitecture

Le matériel est souvent réputé plus robuste aux attaques logicielles, car il ne peut être modifié. Toutefois, les architectures des processeurs sont de plus en plus complexes et implémentent de nombreux mécanismes qui peuvent interférer entre eux. Des erreurs dans la spécification de ces mécanismes peuvent conduire à des vulnérabilités permettant de contourner les mécanismes de sécurité.

L'implémentation de ces architectures est également de plus en plus complexe, pour des raisons d'optimisation de la performance et de la consommation énergétique, qui sont les deux défis principaux auxquels doivent faire face les constructeurs de processeurs. En effet, en raison du power wall, il n'est plus possible d'augmenter facilement les performances des processeurs en augmentant la fréquence de leur horloge, comme cela a été le cas pendant des décennies, sans impliquer une consommation et une dissipation énergétique rédhibitoires. Pour ces raisons, les constructeurs ont concentré leurs efforts sur l'optimisation de la microarchitecture des processeurs. Ces différentes optimisations consistent, d'une manière ou d'une autre, à exécuter un maximum d'instructions en parallèle.

Ainsi, les processeurs modernes comportent généralement plusieurs cœurs indépendants qui permettent d'exécuter plusieurs fils d'instruction en parallèle. Au sein d'un cœur, les opérations de récupération (*fetch*), de décodage (*decode*), d'exécution (*execute*), d'ac-cès mémoire (*memory access*) et de modification de l'état des registres (*writeback*) de ces instructions sont réalisées en parallèle au sein d'un *pipeline*. Ainsi, par exemple, la récupération de la prochaine instruction peut être initiée avant la fin de l'exécution de l'instruction qui la précède.
Une preuve a ensuite été établie que cette spécification respecte une politique de sécurité formellement spécifiée, sous réserve que le BIOS utilise correctement ce mécanisme. Ce dernier point fait l'objet d'hypothèses qui expriment explicitement les contraintes d'utilisation du mécanisme que les développeurs du BIOS doivent respecter. Toutefois, le modèle du processeur utilisé n'est pas complet et la preuve porte uniquement sur la spécification.

Ferraiuolo et al. ont proposé un HDL (Hardware Description Language, langage de description du matériel) fortement typé permettant de spécifier et de prouver des mécanismes d'isolation en utilisant des techniques de vérification des flux d'information, à l'aide d'une analyse statique de vérification du typage [182]. Ils ont appliqué leur approche en implémentant un mécanisme similaire à TrustZone sur un softcore MIPS. Des chercheurs ont proposé une approche similaire en s'appuyant sur Chisel, un HDL de haut niveau utilisé notamment pour implémenter des processeurs RISC-V [183]. Ils vérifient que la politique de flux d'information est respectée à l'aide d'un solveur SMT (Satisfiability Modulo Theories).

Récemment, les chercheurs impliqués dans les projet CHERI et SAIL ont utilisé le langage SAIL pour spécifier l'architecture CHERI et prouver qu'elle garantit certaines propriétés de sécurité, notamment l'évolution monotone des capacités (un attaquant ne peut faire évoluer une capacité pour la rendre plus permissive) [184]. SAIL peut également être utilisé pour tester une implémentation afin de s'assurer qu'elle est conforme à la spécification. Le projet ne permet cependant pas, à l'heure actuelle, de vérifier formellement qu'une implémentation respecte la sémantique de la spécification formelle.

## 2.2 Attaques logicielles contre la microarchitecture

Le matériel est souvent réputé plus robuste aux attaques logicielles, car il ne peut être modifié. Toutefois, les architectures des processeurs sont de plus en plus complexes et implémentent de nombreux mécanismes qui peuvent interférer entre eux. Des erreurs dans la spécification de ces mécanismes peuvent conduire à des vulnérabilités permettant de contourner les mécanismes de sécurité.

L'implémentation de ces architectures est également de plus en plus complexe, pour des raisons d'optimisation de la performance et de la consommation énergétique, qui sont les deux défis principaux auxquels doivent faire face les constructeurs de processeurs. En effet, en raison du power wall, il n'est plus possible d'augmenter facilement les performances des processeurs en augmentant la fréquence de leur horloge, comme cela a été le cas pendant des décennies, sans impliquer une consommation et une dissipation énergétique rédhibitoires. Pour ces raisons, les constructeurs ont concentré leurs efforts sur l'optimisation de la microarchitecture des processeurs. Ces différentes optimisations consistent, d'une manière ou d'une autre, à exécuter un maximum d'instructions en parallèle.

Ainsi, les processeurs modernes comportent généralement plusieurs cœurs indépendants qui permettent d'exécuter plusieurs fils d'instruction en parallèle. Au sein d'un cœur, les opérations de récupération (*fetch*), de décodage (*decode*), d'exécution (*execute*), d'ac-cès mémoire (*memory access*) et de modification de l'état des registres (*writeback*) de ces instructions sont réalisées en parallèle au sein d'un *pipeline*. Ainsi, par exemple, la récupération de la prochaine instruction peut être initiée avant la fin de l'exécution de l'instruction qui la précède.
En outre, les architectures modernes superscalaires comportent plusieurs unités d'exécutions (notamment plusieurs ALU (Arithmetic-Logic Unit, unité arithmétique et logique)) et peuvent donc récupérer et exécuter plusieurs instructions en parallèle, pour un même fil d'exécution ou pour plusieurs fils d'exécution (cœur virtuel ou hyperthreading).

Sur les processeurs x86, les instructions sont traduites par le microprocesseur sous la forme d'une ou plusieurs micro-instructions, qui sont ensuite exécutées. Cette traduction est réalisée par un microcode qui peut être chargé dynamiquement, ce qui permet une forme limitée de mise-à-jour de la microarchitecture. Toutefois, le format de ce microcode n'est pas public.

Afin d'optimiser ce traitement en parallèle, le processeur peut être amené à exécuter des instructions dans le désordre (*out-of-order execution*) et parfois de manière spéculative. En effet, l'exécution de certaines instructions, notamment celles qui réalisent des accès mémoire, peuvent nécessiter un nombre de cycles plus importants que les autres. En outre, certaines instructions peuvent nécessiter des unités d'exécution qui ne sont pas disponibles, à la différence des instructions qui les suivent dans le programme.

Toutefois, les processeurs exposent les résultats de l'exécution de ces instructions au niveau de l'architecture (*Retirement Unit*), en respectant l'ordre des instructions. Si une exception s'est produite, le processeur peut décider de ne pas exposer le résultat de certaines instructions au niveau de l'architecture. L'état des registres exposé par l'architecture est alors restauré à celui précédent l'instruction fautive.

En outre, le processeur peut inférer les prochaines instructions à exécuter. Cela est notamment nécessaire lors des branchements conditionnels ou des sauts indirects. L'adresse de la prochaine instruction dépend alors du résultat des instructions précédentes, qui peut ne pas être disponible. Le processeur vérifie *a posteriori* que la prédiction était correcte et, en cas d'erreur, annule l'exécution des instructions exécutées spéculativement, en s'assurant que l'état de l'architecture est identique à celui précédant l'exécution de ces instructions.

L'exécution spéculative et l'exécution dans le désordre peuvent donc conduire à annuler l'exécution de certaines instructions. La littérature emploie le terme d'exécution transitoire (*transient execution*) pour désigner l'exécution de ces instructions avant qu'elle ne soit validée et exposée au niveau de l'architecture.

En outre, la microarchitecture repose généralement sur un ou plusieurs niveaux de mémoire cache. Les caches ont un temps d'accès beaucoup plus faible que la mémoire principale (DRAM). Toutefois, leur taille est limitée en raison de leur coût. Ils permettent d'accélérer les accès mémoire tout en donnant l'illusion au logiciel de disposer d'une quantité importante de mémoire (correspondant à la taille de la DRAM) avec un faible temps d'accès. L'accès au cache est transparent pour le développeur de l'application.

A la différence de l'architecture, les détails de la microarchitecture sont en général peu documentés et évoluent entre les différentes versions des processeurs. Les différentes optimisations de la microarchitecture ont donné lieu à des vulnérabilités exploitables par le logiciel [185]. Ces attaques contre la microarchitecture s'expliquent notamment par le fait que plusieurs fils d'exécution partagent des ressources (cache, unité d'exécution, etc.) et que l'état de la microarchitecture peut être en partie visible par différents programmes s'exécutant en parallèle ou en temps partagé (l'état de la microarchitecture n'étant pas réinitialisé entre chaque changement de contexte). Ces attaques peuvent donc contourner
En outre, les architectures modernes superscalaires comportent plusieurs unités d'exécutions (notamment plusieurs ALU (Arithmetic-Logic Unit, unité arithmétique et logique)) et peuvent donc récupérer et exécuter plusieurs instructions en parallèle, pour un même fil d'exécution ou pour plusieurs fils d'exécution (cœur virtuel ou hyperthreading).

Sur les processeurs x86, les instructions sont traduites par le microprocesseur sous la forme d'une ou plusieurs micro-instructions, qui sont ensuite exécutées. Cette traduction est réalisée par un microcode qui peut être chargé dynamiquement, ce qui permet une forme limitée de mise-à-jour de la microarchitecture. Toutefois, le format de ce microcode n'est pas public.

Afin d'optimiser ce traitement en parallèle, le processeur peut être amené à exécuter des instructions dans le désordre (*out-of-order execution*) et parfois de manière spéculative. En effet, l'exécution de certaines instructions, notamment celles qui réalisent des accès mémoire, peuvent nécessiter un nombre de cycles plus importants que les autres. En outre, certaines instructions peuvent nécessiter des unités d'exécution qui ne sont pas disponibles, à la différence des instructions qui les suivent dans le programme.

Toutefois, les processeurs exposent les résultats de l'exécution de ces instructions au niveau de l'architecture (*Retirement Unit*), en respectant l'ordre des instructions. Si une exception s'est produite, le processeur peut décider de ne pas exposer le résultat de certaines instructions au niveau de l'architecture. L'état des registres exposé par l'architecture est alors restauré à celui précédent l'instruction fautive.

En outre, le processeur peut inférer les prochaines instructions à exécuter. Cela est notamment nécessaire lors des branchements conditionnels ou des sauts indirects. L'adresse de la prochaine instruction dépend alors du résultat des instructions précédentes, qui peut ne pas être disponible. Le processeur vérifie *a posteriori* que la prédiction était correcte et, en cas d'erreur, annule l'exécution des instructions exécutées spéculativement, en s'assurant que l'état de l'architecture est identique à celui précédant l'exécution de ces instructions.

L'exécution spéculative et l'exécution dans le désordre peuvent donc conduire à annuler l'exécution de certaines instructions. La littérature emploie le terme d'exécution transitoire (*transient execution*) pour désigner l'exécution de ces instructions avant qu'elle ne soit validée et exposée au niveau de l'architecture.

En outre, la microarchitecture repose généralement sur un ou plusieurs niveaux de mémoire cache. Les caches ont un temps d'accès beaucoup plus faible que la mémoire principale (DRAM). Toutefois, leur taille est limitée en raison de leur coût. Ils permettent d'accélérer les accès mémoire tout en donnant l'illusion au logiciel de disposer d'une quantité importante de mémoire (correspondant à la taille de la DRAM) avec un faible temps d'accès. L'accès au cache est transparent pour le développeur de l'application.

A la différence de l'architecture, les détails de la microarchitecture sont en général peu documentés et évoluent entre les différentes versions des processeurs. Les différentes optimisations de la microarchitecture ont donné lieu à des vulnérabilités exploitables par le logiciel [185]. Ces attaques contre la microarchitecture s'expliquent notamment par le fait que plusieurs fils d'exécution partagent des ressources (cache, unité d'exécution, etc.) et que l'état de la microarchitecture peut être en partie visible par différents programmes s'exécutant en parallèle ou en temps partagé (l'état de la microarchitecture n'étant pas réinitialisé entre chaque changement de contexte). Ces attaques peuvent donc contourner
les mécanismes d'isolation garantis au niveau de l'architecture.

Nous détaillons par la suite les travaux relatifs aux attaques logicielles par canaux auxiliaires (side channel attacks), dans la section 2.2.1. Ces attaques consistent à exploiter des fuites d'information résultant de l'observation d'une grandeur physique (temps d'exécution, consommation électrique, dissipation thermique, etc.). Contrairement aux attaques physiques, ces observations sont réalisées directement par du logiciel exécuté sur le processeur. Puis nous évoquons en section 2.2.2 les attaques qui exploitent l'exécution transitoire et qui s'appuient sur les attaques par canaux auxiliaires pour faire fuir des données confidentielles. Nous présentons en section 2.2.3 les attaques par injection de fautes, qui permettent de modifier l'état du processeur en contournant les mécanismes d'isolation. Nous nous attardons en section 2.2.4 sur les attaques qui visent plus particulièrement à contourner les mécanismes d'enclave. Enfin, la réalisation d'attaques et l'évaluation de la sécurité des processeurs nécessitent d'obtenir des informations précises sur la microarchitecture. Nous présentons donc en section 2.2.5 les travaux liés à la rétroconception de la microarchitecture.

## 2.2.1 Attaques logicielles par canaux auxiliaires

Les attaques logicielles par canaux auxiliaires visent à mesurer, par l'exécution d'un programme, des effets physiques (temps d'exécution, consommation électrique ou température) qui permettent d'inférer des informations confidentielles appartenant à un autre programme. Ces attaques permettent donc de contourner les mécanismes d'isolation au niveau de l'architecture qui ne prennent pas en compte ce type de menace. Pour ce type d'attaque, l'attaquant maîtrise seulement le code permettant d'effectuer des mesures et cible un programme qui va influencer la grandeur mesurée à son insu. Si cette fluctuation dépend d'une valeur confidentielle, une fuite d'information est possible.

Ces attaques sont à distinguer des attaques par canal caché. Dans ce dernier cas, l'attaquant contrôle les deux extrémités du canal de communication. Il s'agit donc d'un modèle d'attaquant plus puissant et qui est souvent moins réaliste. Toutefois, la mise aux point d'une attaque par canal caché peut être une première étape dans l'analyse des attaques par canaux auxiliaires.

Des chercheurs ont dressé un état de l'art et une classification de ces attaques [186, 187]. La plupart des travaux de la littérature s'intéressent aux canaux temporels pour lesquels l'attaquant peut mesurer une différence de temps d'exécution. Ces différences peuvent résulter de plusieurs facteurs :

- selon les chemins parcourus dans le graphe de contrôle du programme, le temps d'exécution peut varier en fonction du nombre et du type d'instructions exécutées;

- le temps d'exécution d'une instruction d'accès à la mémoire varie en fonction de l'état des caches (l'accès est plus rapide si la donnée ou l'instruction est présente dans le cache);

- dans les architectures superscalaires, le temps d'exécution d'une instruction dépend de l'état de disponibilité des unités d'exécution nécessaires à l'exécution de l'instruction.

La plupart des travaux sur l'exploitation des canaux auxiliaires temporels se sont intéressés à ceux résultant de l'utilisation des caches. Toutefois, des travaux ont également démontré que la variation de temps d'exécution liée à la disponibilité des unités d'exécution (port
les mécanismes d'isolation garantis au niveau de l'architecture.

Nous détaillons par la suite les travaux relatifs aux attaques logicielles par canaux auxiliaires (side channel attacks), dans la section 2.2.1. Ces attaques consistent à exploiter des fuites d'information résultant de l'observation d'une grandeur physique (temps d'exécution, consommation électrique, dissipation thermique, etc.). Contrairement aux attaques physiques, ces observations sont réalisées directement par du logiciel exécuté sur le processeur. Puis nous évoquons en section 2.2.2 les attaques qui exploitent l'exécution transitoire et qui s'appuient sur les attaques par canaux auxiliaires pour faire fuir des données confidentielles. Nous présentons en section 2.2.3 les attaques par injection de fautes, qui permettent de modifier l'état du processeur en contournant les mécanismes d'isolation. Nous nous attardons en section 2.2.4 sur les attaques qui visent plus particulièrement à contourner les mécanismes d'enclave. Enfin, la réalisation d'attaques et l'évaluation de la sécurité des processeurs nécessitent d'obtenir des informations précises sur la microarchitecture. Nous présentons donc en section 2.2.5 les travaux liés à la rétroconception de la microarchitecture.

## 2.2.1 Attaques logicielles par canaux auxiliaires

Les attaques logicielles par canaux auxiliaires visent à mesurer, par l'exécution d'un programme, des effets physiques (temps d'exécution, consommation électrique ou température) qui permettent d'inférer des informations confidentielles appartenant à un autre programme. Ces attaques permettent donc de contourner les mécanismes d'isolation au niveau de l'architecture qui ne prennent pas en compte ce type de menace. Pour ce type d'attaque, l'attaquant maîtrise seulement le code permettant d'effectuer des mesures et cible un programme qui va influencer la grandeur mesurée à son insu. Si cette fluctuation dépend d'une valeur confidentielle, une fuite d'information est possible.

Ces attaques sont à distinguer des attaques par canal caché. Dans ce dernier cas, l'attaquant contrôle les deux extrémités du canal de communication. Il s'agit donc d'un modèle d'attaquant plus puissant et qui est souvent moins réaliste. Toutefois, la mise aux point d'une attaque par canal caché peut être une première étape dans l'analyse des attaques par canaux auxiliaires.

Des chercheurs ont dressé un état de l'art et une classification de ces attaques [186, 187]. La plupart des travaux de la littérature s'intéressent aux canaux temporels pour lesquels l'attaquant peut mesurer une différence de temps d'exécution. Ces différences peuvent résulter de plusieurs facteurs :

- selon les chemins parcourus dans le graphe de contrôle du programme, le temps d'exécution peut varier en fonction du nombre et du type d'instructions exécutées;

- le temps d'exécution d'une instruction d'accès à la mémoire varie en fonction de l'état des caches (l'accès est plus rapide si la donnée ou l'instruction est présente dans le cache);

- dans les architectures superscalaires, le temps d'exécution d'une instruction dépend de l'état de disponibilité des unités d'exécution nécessaires à l'exécution de l'instruction.

La plupart des travaux sur l'exploitation des canaux auxiliaires temporels se sont intéressés à ceux résultant de l'utilisation des caches. Toutefois, des travaux ont également démontré que la variation de temps d'exécution liée à la disponibilité des unités d'exécution (port
contention) pouvait également être exploitée [188] lorsque plusieurs files d'exécution sont exécutées simultanément sur un même cœur physique (hyper-threading).

Ces attaques nécessitent d'identifier une ressource partagée et de réaliser un travail de rétroconception, bien souvent spécifique à chaque microarchitecture, afin de pouvoir éventuellement l'exploiter. Gras et al. ont proposé ABSynthe [189], une approche en boîte noire permettant d'identifier automatiquement des canaux cachés de type port contention à partir d'un programme cible et d'une microarchitecture, sans nécessiter d'effort de rétroconception explicite de la microarchitecture.

### 2.2.1.1 Exploitation des temps d'accès aux caches

Plusieurs types d'attaques contre les caches ont été mis en évidence dans la littérature. Ainsi, Osvik et al. sont parmi les premiers à démontrer la faisabilité de ce type d'attaques [190]. Les auteurs cherchent à retrouver la clé secrète AES utilisée par un processus ou par le noyau Linux, à partir d'un second processus. Ils démontrent ainsi que ce type d'attaque permet de contourner l'isolation fournie par le mécanisme de pagination de la mémoire. Ils utilisent pour cela une attaque de type EVICT+TIME. Cette attaque consiste à évincer des données d'une ligne de cache puis de mesurer le temps d'exécution du programme victime afin de déterminer s'il a réalisé un accès mémoire à une adresse correspondant à cette ligne de cache.

Les auteurs utilisent également une attaque de type PRIME+PROBE qui consiste à précharger toutes les lignes d'un même ensemble puis à lire les adresses correspondant à ces lignes. Un temps d'accès plus long signifie que le programme victime a réalisé un accès mémoire correspondant à cet ensemble. Ces attaques visent le cache de premier niveau (L1) et doivent donc être exécutées sur le même cœur physique que la victime.

Zhang et al. ont également démontré que ce type d'attaque était possible entre différentes machines virtuelles s'exécutant sur différents cœurs d'un processeur [191]. Toutefois, l'attaque nécessite un filtrage complexe du bruit généré notamment par l'exécution de l'hyperviseur et le débit du canal auxiliaire est relativement lent (l'attaque nécessite six heures d'observation pour retrouver une clé cryptographique).

Plus récemment, Yarom et al. ont démontré que le partage de pages mémoire entre processus, par exemple les pages de code des bibliothèques partagées, permet de réaliser une attaque de type FLUSH + RELOAD [192]. Ce type d'attaque présente un bon rapport signal sur bruit et permet des débits plus importants. L'attaque consiste à vider une ligne de cache avant d'exécuter le processus victime puis de réaliser une lecture à une adresse correspondant à cette ligne. Un faible temps d'accès permet alors d'inférer que la victime a réalisé une lecture à une adresse correspondant à cette ligne.

Contrairement aux attaques précédentes, les auteurs exploitent le LLC (Last Level Cache), qui est partagé entre les différents cœurs d'un microprocesseur. Le processus de l'attquant ne doit donc plus nécessairement être exécuté sur le même cœur que le processus victime. Les auteurs démontrent qu'il est possible de retrouver la clé privée utilisée par un processus exécutant le logiciel de chiffrement GnuPG. Apecechea et al. ont confirmé que cette attaque pouvait être utilisée entre différentes machines virtuelles d'un même serveur [193]. Enfin, Zhang et al. ont démontré que cette attaque est également possible sur les processeurs ARM [194].

Les attaques FLUSH+RELOAD sont très performantes et permettent de contourner
contention) pouvait également être exploitée [188] lorsque plusieurs files d'exécution sont exécutées simultanément sur un même cœur physique (hyper-threading).

Ces attaques nécessitent d'identifier une ressource partagée et de réaliser un travail de rétroconception, bien souvent spécifique à chaque microarchitecture, afin de pouvoir éventuellement l'exploiter. Gras et al. ont proposé ABSynthe [189], une approche en boîte noire permettant d'identifier automatiquement des canaux cachés de type port contention à partir d'un programme cible et d'une microarchitecture, sans nécessiter d'effort de rétroconception explicite de la microarchitecture.

### 2.2.1.1 Exploitation des temps d'accès aux caches

Plusieurs types d'attaques contre les caches ont été mis en évidence dans la littérature. Ainsi, Osvik et al. sont parmi les premiers à démontrer la faisabilité de ce type d'attaques [190]. Les auteurs cherchent à retrouver la clé secrète AES utilisée par un processus ou par le noyau Linux, à partir d'un second processus. Ils démontrent ainsi que ce type d'attaque permet de contourner l'isolation fournie par le mécanisme de pagination de la mémoire. Ils utilisent pour cela une attaque de type EVICT+TIME. Cette attaque consiste à évincer des données d'une ligne de cache puis de mesurer le temps d'exécution du programme victime afin de déterminer s'il a réalisé un accès mémoire à une adresse correspondant à cette ligne de cache.

Les auteurs utilisent également une attaque de type PRIME+PROBE qui consiste à précharger toutes les lignes d'un même ensemble puis à lire les adresses correspondant à ces lignes. Un temps d'accès plus long signifie que le programme victime a réalisé un accès mémoire correspondant à cet ensemble. Ces attaques visent le cache de premier niveau (L1) et doivent donc être exécutées sur le même cœur physique que la victime.

Zhang et al. ont également démontré que ce type d'attaque était possible entre différentes machines virtuelles s'exécutant sur différents cœurs d'un processeur [191]. Toutefois, l'attaque nécessite un filtrage complexe du bruit généré notamment par l'exécution de l'hyperviseur et le débit du canal auxiliaire est relativement lent (l'attaque nécessite six heures d'observation pour retrouver une clé cryptographique).

Plus récemment, Yarom et al. ont démontré que le partage de pages mémoire entre processus, par exemple les pages de code des bibliothèques partagées, permet de réaliser une attaque de type FLUSH + RELOAD [192]. Ce type d'attaque présente un bon rapport signal sur bruit et permet des débits plus importants. L'attaque consiste à vider une ligne de cache avant d'exécuter le processus victime puis de réaliser une lecture à une adresse correspondant à cette ligne. Un faible temps d'accès permet alors d'inférer que la victime a réalisé une lecture à une adresse correspondant à cette ligne.

Contrairement aux attaques précédentes, les auteurs exploitent le LLC (Last Level Cache), qui est partagé entre les différents cœurs d'un microprocesseur. Le processus de l'attquant ne doit donc plus nécessairement être exécuté sur le même cœur que le processus victime. Les auteurs démontrent qu'il est possible de retrouver la clé privée utilisée par un processus exécutant le logiciel de chiffrement GnuPG. Apecechea et al. ont confirmé que cette attaque pouvait être utilisée entre différentes machines virtuelles d'un même serveur [193]. Enfin, Zhang et al. ont démontré que cette attaque est également possible sur les processeurs ARM [194].

Les attaques FLUSH+RELOAD sont très performantes et permettent de contourner
l'isolation, notamment celle implémentée par les instructions de virtualisation. Dans le contexte du cloud computing, le partage de ressources doit faire l'objet d'une attention particulière et les fournisseurs configurent l'hyperviseur pour éviter le partage de page mémoire entre différentes machines virtuelles.

Toutefois, Liu et al. ont démontré que la propriété d'inclusion des caches de l'architecture x86 pouvait être exploitée pour réaliser une variante de l'attaque PRIME+PROBE ciblant le LLC, sans nécessiter de partage d'une page mémoire [195]. De même Apecechea et al. sont arrivés à un résultat similaire en utilisant des pages de grandes tailles [196]. Maurice et al. ont également démontré qu'il était possible d'établir un canal caché à l'aide d'une attaque de type PRIME+PROBE entre deux machines virtuelles isolées [197]. Les auteurs ont réussi à déployer des techniques permettant d'établir un canal de communication suffisamment robuste pour supporter une communication SSH entre les deux VM.

Ces attaques génèrent des anomalies dans le nombre de *cache hit* et *cache miss* que des approches ont proposé de détecter, notamment à l'aide des compteurs de performances. Gruss et al. ont proposé une nouvelle attaque de type FLUSH+FLUSH [198] qui exploite le fait que l'instruction permettant de vider une ligne de cache s'exécute plus rapidement si la ligne correspondant à l'adresse indiquée n'est pas contenue dans le cache. Cette attaque ne nécessite pas de réaliser d'accès supplémentaire pour tester si les données sont présentes dans le cache. Toutefois, des techniques de détection ont été proposées permettant de détecter cette attaque. Briongos et al. ont proposé récemment un nouveau type d'attaque, RELOAD+REFRESH [199], dans l'objectif de contourner les mécanismes de détection proposés jusqu'à présent. L'attaque, qui vise le LLC, ne nécessite pas d'évincer une ligne de cache.

Moritz et al. ont démontré que des attaques de type EVICT+RELOAD pouvaient également être réalisées sur les processeurs ARM, couramment utilisés dans les *smart-phone* [200], sans nécessiter de permissions spécifiques.

Disselkoen et al. ont démontré que le mécanisme de mémoire transactionnelle implémenté par Intel TSX, permettait de réaliser une attaque de type PRIME+ABORT [201], qui est une variante de l'attaque PRIME+PROBE. Toutefois, contrairement aux autres attaques, il ne s'agit pas d'un canal temporel qui nécessite que l'attaquant puisse réaliser une mesure précise du temps d'exécution. Elle est donc particulièrement intéressante pour contourner les mécanismes qui visent à restreindre les possibilités de mesure du temps d'exécution. Elle repose sur les propriétés de la mémoire transactionnelle qui utilise le cache pour stocker temporairement les résultats des accès mémoire avant de les valider. L'attaquant débute une transaction et précharge toutes les lignes d'un même ensemble, comme dans l'attaque PRIME+PROBE. Toutefois, dans le cadre de l'attaque PRIME+ABORT, si la victime réalise un accès mémoire à une adresse correspondant au même ensemble, la transaction échoue et l'attaquant est notifié sans avoir besoin d'effectuer de mesure temporelle. L'attaque ne nécessite pas que l'attaquant s'exécute sur le même cœur que la victime ni qu'il ne partage une page mémoire.

Les attaques précédentes permettent de contourner les mécanismes d'isolation des processeurs pour réaliser des atteintes à la confidentialité des données. Toutefois, elles nécessitent que le code ciblé réalise des accès mémoire dont l'adresse dépend de la valeur confidentielle. La réalisation d'une attaque demande donc une étude approfondie du code de l'application ciblée. Gruss et al. ont proposé une approche de type *Cache Template Attacks* permettant d'automatiser les attaques par canal auxiliaire utilisant le LLC [202].
l'isolation, notamment celle implémentée par les instructions de virtualisation. Dans le contexte du cloud computing, le partage de ressources doit faire l'objet d'une attention particulière et les fournisseurs configurent l'hyperviseur pour éviter le partage de page mémoire entre différentes machines virtuelles.

Toutefois, Liu et al. ont démontré que la propriété d'inclusion des caches de l'architecture x86 pouvait être exploitée pour réaliser une variante de l'attaque PRIME+PROBE ciblant le LLC, sans nécessiter de partage d'une page mémoire [195]. De même Apecechea et al. sont arrivés à un résultat similaire en utilisant des pages de grandes tailles [196]. Maurice et al. ont également démontré qu'il était possible d'établir un canal caché à l'aide d'une attaque de type PRIME+PROBE entre deux machines virtuelles isolées [197]. Les auteurs ont réussi à déployer des techniques permettant d'établir un canal de communication suffisamment robuste pour supporter une communication SSH entre les deux VM.

Ces attaques génèrent des anomalies dans le nombre de *cache hit* et *cache miss* que des approches ont proposé de détecter, notamment à l'aide des compteurs de performances. Gruss et al. ont proposé une nouvelle attaque de type FLUSH+FLUSH [198] qui exploite le fait que l'instruction permettant de vider une ligne de cache s'exécute plus rapidement si la ligne correspondant à l'adresse indiquée n'est pas contenue dans le cache. Cette attaque ne nécessite pas de réaliser d'accès supplémentaire pour tester si les données sont présentes dans le cache. Toutefois, des techniques de détection ont été proposées permettant de détecter cette attaque. Briongos et al. ont proposé récemment un nouveau type d'attaque, RELOAD+REFRESH [199], dans l'objectif de contourner les mécanismes de détection proposés jusqu'à présent. L'attaque, qui vise le LLC, ne nécessite pas d'évincer une ligne de cache.

Moritz et al. ont démontré que des attaques de type EVICT+RELOAD pouvaient également être réalisées sur les processeurs ARM, couramment utilisés dans les *smart-phone* [200], sans nécessiter de permissions spécifiques.

Disselkoen et al. ont démontré que le mécanisme de mémoire transactionnelle implémenté par Intel TSX, permettait de réaliser une attaque de type PRIME+ABORT [201], qui est une variante de l'attaque PRIME+PROBE. Toutefois, contrairement aux autres attaques, il ne s'agit pas d'un canal temporel qui nécessite que l'attaquant puisse réaliser une mesure précise du temps d'exécution. Elle est donc particulièrement intéressante pour contourner les mécanismes qui visent à restreindre les possibilités de mesure du temps d'exécution. Elle repose sur les propriétés de la mémoire transactionnelle qui utilise le cache pour stocker temporairement les résultats des accès mémoire avant de les valider. L'attaquant débute une transaction et précharge toutes les lignes d'un même ensemble, comme dans l'attaque PRIME+PROBE. Toutefois, dans le cadre de l'attaque PRIME+ABORT, si la victime réalise un accès mémoire à une adresse correspondant au même ensemble, la transaction échoue et l'attaquant est notifié sans avoir besoin d'effectuer de mesure temporelle. L'attaque ne nécessite pas que l'attaquant s'exécute sur le même cœur que la victime ni qu'il ne partage une page mémoire.

Les attaques précédentes permettent de contourner les mécanismes d'isolation des processeurs pour réaliser des atteintes à la confidentialité des données. Toutefois, elles nécessitent que le code ciblé réalise des accès mémoire dont l'adresse dépend de la valeur confidentielle. La réalisation d'une attaque demande donc une étude approfondie du code de l'application ciblée. Gruss et al. ont proposé une approche de type *Cache Template Attacks* permettant d'automatiser les attaques par canal auxiliaire utilisant le LLC [202].
Leur approche ne nécessite pas d'analyser le code de l'application. Elle repose sur une première phase permettant d'analyser les accès mémoire de l'application pour différents événements ciblés, en mesurant le *cache hit ratio* sur différentes adresses mémoires. Les événements peuvent être de diverses natures telles que la frappe d'une touche du clavier, la réception d'un email ou le chiffrement à l'aide d'un élément spécifique d'une clé. La phase d'attaque consiste à exploiter les profils ainsi obtenus. Les deux phases reposent sur des attaques FLUSH+RELOAD.

Les attaques précédentes supposent que l'attaquant et la victime s'exécutent sur le même processeur, même s'ils peuvent potentiellement s'exécuter sur des cœurs différents. Ira-zoqui et al. ont démontré la faisabilité d'attaques par canaux auxiliaire entre différents processeurs d'un ordinateur utilisant une configuration à plusieurs processeurs reliés par un bus d'interconnexion comme AMD HyperTransport ou Intel Quickpath [203].

Allan et al. ont montré que les attaques par dégradation des performances permettaient d'amplifier les attaques par canaux auxiliaires [204]. Pour ce type d'attaques, l'attaquant cherche délibérément à utiliser les ressources partagées avec la victime, ce qui a pour effet de ralentir l'exécution du code de la victime. Ce ralentissement facilite la réalisation d'une attaque par canal auxiliaire.

Les attaques sur le LLC sont les moins contraignantes pour l'attaquant car elles ne né-cessitent pas que le processus attaquant s'exécute sur le même cœur que sa cible. Elles sont donc particulièrement redoutées dans un contexte de *cloud computing*. Toutefois, comme évoqué précédemment, les attaques nécessitant le partage d'une page mémoire sont maintenant prises en compte par les fournisseurs de *cloud* qui évitent le partage de pages mémoire entre machines virtuelles. En outre, les autres types d'attaques reposent sur la propriété d'inclusion des caches. Toutefois, ces attaques sont remises en cause par les nouvelles architectures de processeurs qui ne présentent plus cette propriété d'inclu-sion. Yan et al. ont cependant proposé une variante de l'attaque PRIME+PROBE qui fonctionne également pour ce type de configuration [205].

Les attaques précédentes visent les caches de données et d'instructions. Des contre-mesures logicielles, s'appuyant sur des fonctionnalités matérielles comme TSX ou CAT (Cache Al-location Technology), ont été proposées pour lutter contre ces attaques. Toutefois, Gras et al. ont démontré que d'autres caches partagés pouvaient être exploités [206], notamment le TLB (Translation Lookaside Buffer) utilisé dans la traduction des adresses virtuelles.

En outre, des contre-mesures purement logicielles ont été proposées afin de séparer les ensembles du LLC entre différents domaines de sécurité. Pour cela, ces approches exploitent la manière dont les adresses physiques sont associées aux ensembles du LLC. L'objectif est de restreindre les adresses utilisables par le code sous le contrôle potentiel d'un atta-quant afin qu'il ne puisse accéder aux ensembles du cache correspondant au code sensible, manipulant des données confidentielles. Toutefois, van Schaik et al. ont montré que ces approches pouvaient être contournées en exploitant un composant matériel de confiance, comme la MMU (Memory Managment Unit) [207]. En effet, ce composant peut également utiliser le cache pour stocker des structures de données qu'il utilise, comme les tables de pages. Comme ces accès ne sont pas réalisés directement par l'exécution d'instructions d'accès à la mémoire, ils ne sont pas protégés.

La même équipe de recherche a également démontré qu'il était possible de casser le mé-canisme d'ASLR en réalisant une attaque de type EVICT+TIME contre le processus
Leur approche ne nécessite pas d'analyser le code de l'application. Elle repose sur une première phase permettant d'analyser les accès mémoire de l'application pour différents événements ciblés, en mesurant le *cache hit ratio* sur différentes adresses mémoires. Les événements peuvent être de diverses natures telles que la frappe d'une touche du clavier, la réception d'un email ou le chiffrement à l'aide d'un élément spécifique d'une clé. La phase d'attaque consiste à exploiter les profils ainsi obtenus. Les deux phases reposent sur des attaques FLUSH+RELOAD.

Les attaques précédentes supposent que l'attaquant et la victime s'exécutent sur le même processeur, même s'ils peuvent potentiellement s'exécuter sur des cœurs différents. Ira-zoqui et al. ont démontré la faisabilité d'attaques par canaux auxiliaire entre différents processeurs d'un ordinateur utilisant une configuration à plusieurs processeurs reliés par un bus d'interconnexion comme AMD HyperTransport ou Intel Quickpath [203].

Allan et al. ont montré que les attaques par dégradation des performances permettaient d'amplifier les attaques par canaux auxiliaires [204]. Pour ce type d'attaques, l'attaquant cherche délibérément à utiliser les ressources partagées avec la victime, ce qui a pour effet de ralentir l'exécution du code de la victime. Ce ralentissement facilite la réalisation d'une attaque par canal auxiliaire.

Les attaques sur le LLC sont les moins contraignantes pour l'attaquant car elles ne né-cessitent pas que le processus attaquant s'exécute sur le même cœur que sa cible. Elles sont donc particulièrement redoutées dans un contexte de *cloud computing*. Toutefois, comme évoqué précédemment, les attaques nécessitant le partage d'une page mémoire sont maintenant prises en compte par les fournisseurs de *cloud* qui évitent le partage de pages mémoire entre machines virtuelles. En outre, les autres types d'attaques reposent sur la propriété d'inclusion des caches. Toutefois, ces attaques sont remises en cause par les nouvelles architectures de processeurs qui ne présentent plus cette propriété d'inclu-sion. Yan et al. ont cependant proposé une variante de l'attaque PRIME+PROBE qui fonctionne également pour ce type de configuration [205].

Les attaques précédentes visent les caches de données et d'instructions. Des contre-mesures logicielles, s'appuyant sur des fonctionnalités matérielles comme TSX ou CAT (Cache Al-location Technology), ont été proposées pour lutter contre ces attaques. Toutefois, Gras et al. ont démontré que d'autres caches partagés pouvaient être exploités [206], notamment le TLB (Translation Lookaside Buffer) utilisé dans la traduction des adresses virtuelles.

En outre, des contre-mesures purement logicielles ont été proposées afin de séparer les ensembles du LLC entre différents domaines de sécurité. Pour cela, ces approches exploitent la manière dont les adresses physiques sont associées aux ensembles du LLC. L'objectif est de restreindre les adresses utilisables par le code sous le contrôle potentiel d'un atta-quant afin qu'il ne puisse accéder aux ensembles du cache correspondant au code sensible, manipulant des données confidentielles. Toutefois, van Schaik et al. ont montré que ces approches pouvaient être contournées en exploitant un composant matériel de confiance, comme la MMU (Memory Managment Unit) [207]. En effet, ce composant peut également utiliser le cache pour stocker des structures de données qu'il utilise, comme les tables de pages. Comme ces accès ne sont pas réalisés directement par l'exécution d'instructions d'accès à la mémoire, ils ne sont pas protégés.

La même équipe de recherche a également démontré qu'il était possible de casser le mé-canisme d'ASLR en réalisant une attaque de type EVICT+TIME contre le processus
de traduction d'adresses réalisé par la MMU, en observant les données mises en cache
par cette dernière [208]. Les chercheurs ont démontré que cette attaque fonctionnait sur
les processeurs ARM, Intel et AMD. Des travaux ont également démontré que des at-
taques par canaux auxiliaires temporels pouvaient compromettre l'ASLR au niveau du
code noyau de l'OS [209, 210].

Les attaques présentées dans cette section nécessitent que l'attaquant puisse exécuter du
code générant des accès mémoire à des adresses spécifiques et puisse mesurer précisément
des temps d'exécution. Ces contraintes laissent à penser que ce type d'attaque ne peut être
réalisé que par un attaquant disposant déjà d'un accès à la machine. Toutefois, des travaux
ont montré que ces attaques pouvait également être réalisées à partir de programmes
JavaScript exécutés dans un navigateur. L'attaque peut donc être réalisée à distance
par un attaquant qui réussit à convaincre un utilisateur de naviguer sur une page Web
contenant le script malveillant. Il est alors possible de réaliser des attaques contournant les
restrictions de la sandbox JavaScript et d'espionner la mémoire d'autres processus [211].
Shusterman et al. ont également démontré que de telles attaques pouvaient permettre de
réaliser des attaques de type website fingerprinting permettant à l'attaquant d'inférer les
sites Web visités par la victime dans d'autres onglets de son navigateur [212].

2.2.1.2 Exploitation de la température et de la consommation électrique

Des travaux se sont intéressés à d'autres types de canaux auxiliaires exploitables par des
attaques logicielles, notamment ceux liés à la température et la consommation électrique.
Toutefois, les attaques purement logicielles exploitant ce type de canal auxiliaire ont pour
l'instant fait l'objet de moins de travaux de recherche.

Masti et al. ont ainsi démontré qu'il était possible d'exploiter l'information sur la tempé-
rature, fournie par les capteurs intégrés aux différents cœurs d'un microprocesseur pour
la gestion dynamique de la consommation énergétique et de la température du proces-
seur [213]. Cette température est potentiellement influencée par la charge des cœurs
adjacents, ce qui permet de créer un canal caché de 12.5 bps.

Lipp et al. ont récemment exploité l'interface RAPL (Running Average Power Limit) des
processeurs Intel qui expose de manière non privilégiée des données corrélées à la consom-
mation électrique des cœurs du microprocesseur [214]. A l'aide de ce canal auxiliaire, les
auteurs ont pu faire fuir une clé AES-NI d'un code exécuté au sein d'une enclave SGX et
casser l'ASLR utilisée au sein du noyau.

2.2.2 Exploitation de l'exécution transitoire

Les attaques logicielles par canaux auxiliaires, notamment celles utilisant les caches, ex-
ploitent des vulnérabilités matérielles qui résultent du partage de ressources entre des
domaines qui devraient être normalement isolés (par exemple, différents processus ou dif-
férentes machines virtuelles). Toutefois, elle s'appuient également sur le fait que le code
de la victime réalise des accès mémoire qui dépendent d'une information confidentielle.
Ces contre-mesures logicielles existent pour éviter ce type de motifs dans les algorithmes
cryptographiques, mais sont difficilement généralisables à tout type de logiciel.

Plus récemment, un nouveau type d'attaques contre la microarchitecture est apparu : les
attaques exploitant l'exécution transitoire. Ces attaques utilisent des canaux auxiliaires
pour faire fuir des données mais elles exploitent à la base des vulnérabilités différentes,
de traduction d'adresses réalisé par la MMU, en observant les données mises en cache
par cette dernière [208]. Les chercheurs ont démontré que cette attaque fonctionnait sur
les processeurs ARM, Intel et AMD. Des travaux ont également démontré que des at-
taques par canaux auxiliaires temporels pouvaient compromettre l'ASLR au niveau du
code noyau de l'OS [209, 210].

Les attaques présentées dans cette section nécessitent que l'attaquant puisse exécuter du
code générant des accès mémoire à des adresses spécifiques et puisse mesurer précisément
des temps d'exécution. Ces contraintes laissent à penser que ce type d'attaque ne peut être
réalisé que par un attaquant disposant déjà d'un accès à la machine. Toutefois, des travaux
ont montré que ces attaques pouvait également être réalisées à partir de programmes
JavaScript exécutés dans un navigateur. L'attaque peut donc être réalisée à distance
par un attaquant qui réussit à convaincre un utilisateur de naviguer sur une page Web
contenant le script malveillant. Il est alors possible de réaliser des attaques contournant les
restrictions de la sandbox JavaScript et d'espionner la mémoire d'autres processus [211].
Shusterman et al. ont également démontré que de telles attaques pouvaient permettre de
réaliser des attaques de type website fingerprinting permettant à l'attaquant d'inférer les
sites Web visités par la victime dans d'autres onglets de son navigateur [212].

2.2.1.2 Exploitation de la température et de la consommation électrique

Des travaux se sont intéressés à d'autres types de canaux auxiliaires exploitables par des
attaques logicielles, notamment ceux liés à la température et la consommation électrique.
Toutefois, les attaques purement logicielles exploitant ce type de canal auxiliaire ont pour
l'instant fait l'objet de moins de travaux de recherche.

Masti et al. ont ainsi démontré qu'il était possible d'exploiter l'information sur la tempé-
rature, fournie par les capteurs intégrés aux différents cœurs d'un microprocesseur pour
la gestion dynamique de la consommation énergétique et de la température du proces-
seur [213]. Cette température est potentiellement influencée par la charge des cœurs
adjacents, ce qui permet de créer un canal caché de 12.5 bps.

Lipp et al. ont récemment exploité l'interface RAPL (Running Average Power Limit) des
processeurs Intel qui expose de manière non privilégiée des données corrélées à la consom-
mation électrique des cœurs du microprocesseur [214]. A l'aide de ce canal auxiliaire, les
auteurs ont pu faire fuir une clé AES-NI d'un code exécuté au sein d'une enclave SGX et
casser l'ASLR utilisée au sein du noyau.

## 2.2.2 Exploitation de l'exécution transitoire

Les attaques logicielles par canaux auxiliaires, notamment celles utilisant les caches, ex-
ploitent des vulnérabilités matérielles qui résultent du partage de ressources entre des
domaines qui devraient être normalement isolés (par exemple, différents processus ou dif-
férentes machines virtuelles). Toutefois, elle s'appuient également sur le fait que le code
de la victime réalise des accès mémoire qui dépendent d'une information confidentielle.
Ces contre-mesures logicielles existent pour éviter ce type de motifs dans les algorithmes
cryptographiques, mais sont difficilement généralisables à tout type de logiciel.

Plus récemment, un nouveau type d'attaques contre la microarchitecture est apparu : les
attaques exploitant l'exécution transitoire. Ces attaques utilisent des canaux auxiliaires
pour faire fuir des données mais elles exploitent à la base des vulnérabilités différentes,
liées à l'exécution spéculative et *out-of-order*. Ces attaques ont été révélées avec les failles Meltdown [215] et Spectre [216]. D'autres types de vulnérabilités ont depuis été mises à jour.

Des travaux ont récemment dressé un état de l'art de ces différentes attaques et des vulnérabilités qu'elles exploitent [217, 218]. Google maintient également un répertoire contenant des exemples illustrant ces différentes attaques [219].

Plusieurs chercheurs impliqués dans la découverte des vulnérabilités Spectre et Meltdown ainsi que leurs variantes, proposent d'adopter une classification que nous reprenons dans ce rapport [217]. Cette classification est également mise à jour sur le site web mis en place par les auteurs [220]. Ainsi, les auteurs distinguent tout d'abord les attaques de type Spectre et celles de type Meltdown.

Les attaques de type Meltdown exploitent l'exécution *out-of-order* des instructions et plus précisément le fait que le traitement des exceptions est retardé. Lorsque l'exécution d'une instruction provoque une exception, par exemple un défaut de page, plusieurs instructions consécutives à l'instruction fautive sont exécutées de manière transitoire avant que l'exception ne soit traitée. Lors du traitement de l'exception, le processeur annule les effets architecturaux de ces instructions. Ainsi, les registres sont restaurés à leur état précédant l'exécution de ces instructions. Toutefois, pour des raison de performance, l'état de la microarchitecture n'est pas modifié. Cela inclut notamment l'état des caches. Comme les instructions ne permettent pas directement d'accéder à l'état de la microarchitecture, le mécanisme était réputé sûr.

Les travaux présentés dans la section précédente ont cependant démontré qu'il était possible d'utiliser des attaques par canal auxiliaire pour faire fuir l'état de la microarchitecture, notamment en mesurant des temps d'accès. Les attaques de type Meltdown consistent donc à provoquer sciemment une exception qui va permettre à l'attaquant de forcer le processeur à exécuter son code de manière transitoire, dans un domaine de protection auquel il n'a normalement pas accès (par exemple, le mode noyau). Ces instructions auront alors accès à l'espace mémoire du domaine de protection et vont faire fuir des données situées dans cet espace mémoire, en utilisant un canal auxiliaire. Le motif typique consiste à réaliser un accès mémoire à une adresse correspondant à la valeur que l'on souhaite faire fuir. Les attaques de types Meltown sont les plus critiques car elles permettent à l'attaquant de faire exécuter son propre code de manière transitoire, ce qui lui donne un contrôle important.

Les attaques de type Spectre exploitent l'exécution spéculative liée aux branchements conditionnels, aux sauts indirects ou aux retours de fonction. L'attaquant cherche à influencer les différents mécanismes de prédiction du processeur pour forcer l'exécution spéculative, dans le processus victime, d'une séquence d'instructions (*gadget*). Cette séquence lui permet de faire fuir des informations confidentielles du processus victime, à l'aide d'un canal auxiliaire. Il s'agit donc d'une forme de *code reuse attack*. Toutefois, les *gadget* sont exécutés de manière spéculative et ne peuvent faire fuir de l'information qu'à l'aide d'un canal auxiliaire, car l'état de l'architecture est restauré par le processeur lorsqu'il détecte l'erreur de spéculation. Ces attaques sont plus complexes à mettre en œuvre car elles reposent sur la présence de *gadget* dans le code de la victime et elles nécessitent d'influencer les mécanismes de prédiction utilisés pour le code de la victime. Elles sont aussi plus difficiles à contrer que l'attaque Meltdown.
liées à l'exécution spéculative et *out-of-order*. Ces attaques ont été révélées avec les failles Meltdown [215] et Spectre [216]. D'autres types de vulnérabilités ont depuis été mises à jour.

Des travaux ont récemment dressé un état de l'art de ces différentes attaques et des vulnérabilités qu'elles exploitent [217, 218]. Google maintient également un répertoire contenant des exemples illustrant ces différentes attaques [219].

Plusieurs chercheurs impliqués dans la découverte des vulnérabilités Spectre et Meltdown ainsi que leurs variantes, proposent d'adopter une classification que nous reprenons dans ce rapport [217]. Cette classification est également mise à jour sur le site web mis en place par les auteurs [220]. Ainsi, les auteurs distinguent tout d'abord les attaques de type Spectre et celles de type Meltdown.

Les attaques de type Meltdown exploitent l'exécution *out-of-order* des instructions et plus précisément le fait que le traitement des exceptions est retardé. Lorsque l'exécution d'une instruction provoque une exception, par exemple un défaut de page, plusieurs instructions consécutives à l'instruction fautive sont exécutées de manière transitoire avant que l'exception ne soit traitée. Lors du traitement de l'exception, le processeur annule les effets architecturaux de ces instructions. Ainsi, les registres sont restaurés à leur état précédant l'exécution de ces instructions. Toutefois, pour des raison de performance, l'état de la microarchitecture n'est pas modifié. Cela inclut notamment l'état des caches. Comme les instructions ne permettent pas directement d'accéder à l'état de la microarchitecture, le mécanisme était réputé sûr.

Les travaux présentés dans la section précédente ont cependant démontré qu'il était possible d'utiliser des attaques par canal auxiliaire pour faire fuir l'état de la microarchitecture, notamment en mesurant des temps d'accès. Les attaques de type Meltdown consistent donc à provoquer sciemment une exception qui va permettre à l'attaquant de forcer le processeur à exécuter son code de manière transitoire, dans un domaine de protection auquel il n'a normalement pas accès (par exemple, le mode noyau). Ces instructions auront alors accès à l'espace mémoire du domaine de protection et vont faire fuir des données situées dans cet espace mémoire, en utilisant un canal auxiliaire. Le motif typique consiste à réaliser un accès mémoire à une adresse correspondant à la valeur que l'on souhaite faire fuir. Les attaques de types Meltown sont les plus critiques car elles permettent à l'attaquant de faire exécuter son propre code de manière transitoire, ce qui lui donne un contrôle important.

Les attaques de type Spectre exploitent l'exécution spéculative liée aux branchements conditionnels, aux sauts indirects ou aux retours de fonction. L'attaquant cherche à influencer les différents mécanismes de prédiction du processeur pour forcer l'exécution spéculative, dans le processus victime, d'une séquence d'instructions (*gadget*). Cette séquence lui permet de faire fuir des informations confidentielles du processus victime, à l'aide d'un canal auxiliaire. Il s'agit donc d'une forme de *code reuse attack*. Toutefois, les *gadget* sont exécutés de manière spéculative et ne peuvent faire fuir de l'information qu'à l'aide d'un canal auxiliaire, car l'état de l'architecture est restauré par le processeur lorsqu'il détecte l'erreur de spéculation. Ces attaques sont plus complexes à mettre en œuvre car elles reposent sur la présence de *gadget* dans le code de la victime et elles nécessitent d'influencer les mécanismes de prédiction utilisés pour le code de la victime. Elles sont aussi plus difficiles à contrer que l'attaque Meltdown.
Nous détaillons par la suite les différentes variantes de ces attaques qui ont été publiées à ce jour.

### 2.2.2.1 Attaques de type Spectre

Canella et al. classifient les différentes variantes de Spectre selon le mécanisme de prédiction empoisonné par l'attaquant. Ils montrent ensuite que, pour la plupart de ces variantes, l'empoisonnement peut être réalisé dans le même espace d'adressage que la victime ou dans un espace distinct. En outre, l'empoisonnement peut être réalisé par le propre code du programme victime ou par le code d'un processus exécuté par l'attaquant.

Dans l'article originel décrivant la vulnérabilité Spectre [216], deux variantes sont décrites, nommées Spectre-PHT et Spectre-BTB par Canella et al. La première variante consiste à empoisonner le *Pattern History Table* qui est utilisé par le processeur pour inférer si un branchement conditionnel sera pris. L'exploitation consiste à identifier, dans le code de la victime, des motifs de code qui réalisent des vérifications de borne ou de typage avant de réaliser un accès en lecture à un tableau ou une structure. L'empoisonnement permettra d'exécuter du code de manière spéculative en dehors des bornes du tableau et d'inspecter la mémoire du processus victime. La seconde variante consiste à empoisonner le *Branch Target Buffer* qui est utilisé pour déterminer l'adresse d'un branchement indirect.

Maisuradze et al. ont mis à jour une troisième variante, Spectre-RSB, où l'attaquant empoisonne le *Return Stack Buffer* utilisé pour prédire la valeur de l'adresse de retour [221].

Kiriansky [222] présente une variante de Spectre-PHT où le code spéculé effectue une écriture en mémoire. Cette écriture en mémoire, réalisée de manière spéculative, peut elle-même réaliser un *buffer-overflow* et modifier des données dans la mémoire. Ces modifications seront annulées lorsque le processeur détectera l'erreur de spéculation mais elles peuvent permettre de contourner des protections contre Spectre-PHT ou de poursuivre l'exécution spéculative en contrôlant son flot d'exécution.

Les travaux précédents utilisent les caches comme canal auxiliaire. Bhattacharyya et al. ont démontré qu'il est également possible d'utiliser les canaux de type *port contention* [223]. De même Schwarz et al. utilisent un canal auxiliaire reposant sur les différences de temps d'exécution des instructions Intel AVX2 pour réaliser une exploitation à distance d'une faille de type Spectre [224].

Des travaux se sont également intéressés à l'utilisation de ces attaques de type Spectre pour réaliser des attaques plus générales. Par exemple, Wampler et al. utilisent ces attaques pour camoufler des logiciels malveillants [225].

Une des difficultés liée à l'exploitation des failles de type spectre est qu'elle nécessite des gadgets assez longs et complexes. Toutefois, Bhattacharyya et al. ont démontré qu'il était possible de chaîner plusieurs gadgets, comme dans une attaque classique de type ROP [226]. Toutefois, ces gadgets sont exécutés de manière spéculative et la longueur de la chaîne est limitée par le nombre de cycles nécessaires pour que le processeur détecte l'erreur de spéculation.

Göktaş et al. ont proposé de combiner une attaque de type Spectre avec l'exploitation d'une corruption mémoire à l'aide d'une attaque de type *code-reuse attack* permettant de
Nous détaillons par la suite les différentes variantes de ces attaques qui ont été publiées à ce jour.

### 2.2.2.1 Attaques de type Spectre

Canella et al. classifient les différentes variantes de Spectre selon le mécanisme de prédiction empoisonné par l'attaquant. Ils montrent ensuite que, pour la plupart de ces variantes, l'empoisonnement peut être réalisé dans le même espace d'adressage que la victime ou dans un espace distinct. En outre, l'empoisonnement peut être réalisé par le propre code du programme victime ou par le code d'un processus exécuté par l'attaquant.

Dans l'article originel décrivant la vulnérabilité Spectre [216], deux variantes sont décrites, nommées Spectre-PHT et Spectre-BTB par Canella et al. La première variante consiste à empoisonner le *Pattern History Table* qui est utilisé par le processeur pour inférer si un branchement conditionnel sera pris. L'exploitation consiste à identifier, dans le code de la victime, des motifs de code qui réalisent des vérifications de borne ou de typage avant de réaliser un accès en lecture à un tableau ou une structure. L'empoisonnement permettra d'exécuter du code de manière spéculative en dehors des bornes du tableau et d'inspecter la mémoire du processus victime. La seconde variante consiste à empoisonner le *Branch Target Buffer* qui est utilisé pour déterminer l'adresse d'un branchement indirect.

Maisuradze et al. ont mis à jour une troisième variante, Spectre-RSB, où l'attaquant empoisonne le *Return Stack Buffer* utilisé pour prédire la valeur de l'adresse de retour [221].

Kiriansky [222] présente une variante de Spectre-PHT où le code spéculé effectue une écriture en mémoire. Cette écriture en mémoire, réalisée de manière spéculative, peut elle-même réaliser un *buffer-overflow* et modifier des données dans la mémoire. Ces modifications seront annulées lorsque le processeur détectera l'erreur de spéculation mais elles peuvent permettre de contourner des protections contre Spectre-PHT ou de poursuivre l'exécution spéculative en contrôlant son flot d'exécution.

Les travaux précédents utilisent les caches comme canal auxiliaire. Bhattacharyya et al. ont démontré qu'il est également possible d'utiliser les canaux de type *port contention* [223]. De même Schwarz et al. utilisent un canal auxiliaire reposant sur les différences de temps d'exécution des instructions Intel AVX2 pour réaliser une exploitation à distance d'une faille de type Spectre [224].

Des travaux se sont également intéressés à l'utilisation de ces attaques de type Spectre pour réaliser des attaques plus générales. Par exemple, Wampler et al. utilisent ces attaques pour camoufler des logiciels malveillants [225].

Une des difficultés liée à l'exploitation des failles de type spectre est qu'elle nécessite des gadgets assez longs et complexes. Toutefois, Bhattacharyya et al. ont démontré qu'il était possible de chaîner plusieurs gadgets, comme dans une attaque classique de type ROP [226]. Toutefois, ces gadgets sont exécutés de manière spéculative et la longueur de la chaîne est limitée par le nombre de cycles nécessaires pour que le processeur détecte l'erreur de spéculation.

Göktaş et al. ont proposé de combiner une attaque de type Spectre avec l'exploitation d'une corruption mémoire à l'aide d'une attaque de type *code-reuse attack* permettant de
contourner les protections contre Spectre [227]. L'attaque permet *in fine* de casser l'ASLR sans provoquer le crash de l'application.

### 2.2.2.2 Attaques de type Meltdown

Canella et al. classifient les différentes variantes de l'attaque Meltdown selon le type d'exception utilisé.

L'article original présentant la vulnérabilité Meltdown [215] détaille la variante Meltdown-US-L1 qui exploite le mécanisme de défaut de pages et plus précisément l'attribut *user/supervisor* des pages. L'attaque consiste à tenter d'accéder à l'espace mémoire du noyau qui est présent dans l'espace virtuel du processus mais qui n'est normalement pas accessible au code de l'application (les pages possèdent l'attribut *supervisor*). Une contre-mesure a consisté à supprimer les pages du noyau de l'espace d'adressage de l'application lorsque le processeur n'est plus en mode noyau. La vulnérabilité permettait de lire arbitrairement dans l'espace mémoire du noyau et potentiellement dans l'ensemble de la mémoire physique lorsque l'OS réalisait un *mapping* complet de cette mémoire dans son espace virtuel. Canella et al. ont également identifié une variante de cette attaque qui exploite le cache comme canal caché mais permet de contourner la protection mise en place par Intel MPK.

LazyFP est une attaque originellement associée aux attaques de type Spectre [228]. Canella et al. l'ont classifiée comme une variante de type Meltdown (Meltdown-NM-REG). Elle repose sur l'utilisation des registres de l'unité de calcul flottant. Pour éviter de sauvgarder ces registres à chaque changement de contexte, il est possible de les marquer comme indisponibles. Si un autre processus tente de les utiliser, une exception *device-not-available* est levée. Dans ce contexte, l'exécution transitoire des instructions permet de faire fuir l'état de ces registres liés à des données du processus victime.

Différentes variantes de Meldown [229-231] ont été identifiées qui font fuir des données situées dans des *buffer internes* de la microarchitecture Intel. Ces variantes, appelées MDS (Microarchitectural Data Sampling) par Intel exploitent différents types d'exceptions selon le *buffer* utilisé. Ces *buffers* sont internes à chaque cœur physique et peuvent contenir des données provenant d'un autre domaine de protection (par exemple d'une enclave SGX). Ragab et al. ont montré qu'il est également possible d'exploiter le *staging buffer*, qui est partagé entre plusieurs cœurs d'un processeur [232].

Moghimi et al. ont proposé une approche de type *fuzzing* permettant d'identifier différentes variantes d'attaques de type Meltdown [233]. Leur outil leur a permis d'identifier de nouvelles sous-variantes de cette famille d'attaques.

### 2.2.2.3 Attaques de type Load Value Injection

LVI est un troisième type d'attaque exploitant l'exécution transitoire [234]. Tout comme les attaques MDS, elle expoite les *buffer internes* des processeurs Intel. Toutefois, l'attaque fonctionne dans le sens opposé. L'attaquant va empoisonner ces *buffer* avec des valeurs puis provoquer une exception dans le code de la victime. Cette exception aura pour effet l'exécution transitoire d'instructions dans le code de la victime, qui vont lire les valeurs injectées dans le *buffer* et exécuter des *gadgets* similaires à ceux des attaques Spectre. Ces *gadgets* vont faire fuir de l'information de la mémoire de la victime via des canaux auxiliaires.
contourner les protections contre Spectre [227]. L'attaque permet *in fine* de casser l'ASLR sans provoquer le crash de l'application.

### 2.2.2.2 Attaques de type Meltdown

Canella et al. classifient les différentes variantes de l'attaque Meltdown selon le type d'exception utilisé.

L'article original présentant la vulnérabilité Meltdown [215] détaille la variante Meltdown-US-L1 qui exploite le mécanisme de défaut de pages et plus précisément l'attribut *user/supervisor* des pages. L'attaque consiste à tenter d'accéder à l'espace mémoire du noyau qui est présent dans l'espace virtuel du processus mais qui n'est normalement pas accessible au code de l'application (les pages possèdent l'attribut *supervisor*). Une contre-mesure a consisté à supprimer les pages du noyau de l'espace d'adressage de l'application lorsque le processeur n'est plus en mode noyau. La vulnérabilité permettait de lire arbitrairement dans l'espace mémoire du noyau et potentiellement dans l'ensemble de la mémoire physique lorsque l'OS réalisait un *mapping* complet de cette mémoire dans son espace virtuel. Canella et al. ont également identifié une variante de cette attaque qui exploite le cache comme canal caché mais permet de contourner la protection mise en place par Intel MPK.

LazyFP est une attaque originellement associée aux attaques de type Spectre [228]. Canella et al. l'ont classifiée comme une variante de type Meltdown (Meltdown-NM-REG). Elle repose sur l'utilisation des registres de l'unité de calcul flottant. Pour éviter de sauvgarder ces registres à chaque changement de contexte, il est possible de les marquer comme indisponibles. Si un autre processus tente de les utiliser, une exception *device-not-available* est levée. Dans ce contexte, l'exécution transitoire des instructions permet de faire fuir l'état de ces registres liés à des données du processus victime.

Différentes variantes de Meldown [229-231] ont été identifiées qui font fuir des données situées dans des *buffer internes* de la microarchitecture Intel. Ces variantes, appelées MDS (Microarchitectural Data Sampling) par Intel exploitent différents types d'exceptions selon le *buffer* utilisé. Ces *buffers* sont internes à chaque cœur physique et peuvent contenir des données provenant d'un autre domaine de protection (par exemple d'une enclave SGX). Ragab et al. ont montré qu'il est également possible d'exploiter le *staging buffer*, qui est partagé entre plusieurs cœurs d'un processeur [232].

Moghimi et al. ont proposé une approche de type *fuzzing* permettant d'identifier différentes variantes d'attaques de type Meltdown [233]. Leur outil leur a permis d'identifier de nouvelles sous-variantes de cette famille d'attaques.

### 2.2.2.3 Attaques de type Load Value Injection

LVI est un troisième type d'attaque exploitant l'exécution transitoire [234]. Tout comme les attaques MDS, elle expoite les *buffer internes* des processeurs Intel. Toutefois, l'attaque fonctionne dans le sens opposé. L'attaquant va empoisonner ces *buffer* avec des valeurs puis provoquer une exception dans le code de la victime. Cette exception aura pour effet l'exécution transitoire d'instructions dans le code de la victime, qui vont lire les valeurs injectées dans le *buffer* et exécuter des *gadgets* similaires à ceux des attaques Spectre. Ces *gadgets* vont faire fuir de l'information de la mémoire de la victime via des canaux auxiliaires.
### 2.2.3 Attaques logicielles par injection de fautes

Des attaques logicielles par injection de fautes matérielles ont également été mises en évidence dans la littérature. Il s'agit de provoquer une altération d'une grandeur physique qui va provoquer une erreur dans le matériel (par exemple le changement d'une valeur dans la mémoire) qui *in fine* conduira à une défaillance des mécanismes de protection du processeur. Contrairement aux injections de fautes par attaques physiques, la faute est provoquée uniquement par l'exécution d'un programme, ce qui permet de les réaliser potentiellement à distance.

Nous détaillons ici les travaux relatifs à deux types d'injections de fautes par attaques logicielles, qui ont été mis en évidence récemment : les attaques exploitant la gestion de l'énergie (section 2.2.3.1) et les attaques par martellement de la mémoire (*rowhammer*), présentées en section 2.2.3.2.

#### 2.2.3.1 Exploitation logicielle de la gestion de l'énergie

Afin d'optimiser la gestion de la consommation d'électricité, les processeurs disposent de fonctionnalités de gestion dynamique de l'énergie. L'objectif est d'adapter au mieux la consommation énergétique en fonction de la demande, c'est-à-dire de la charge du processeur. Cette fonctionnalité est notamment cruciale pour les systèmes embarqués, les coordinateurs portables ou les *smartphone* alimentés sur batterie. Elle est également liée à la gestion de la dissipation énergétique et de la température du processeur.

Afin de moduler cette consommation énergétique, le processeur peut moduler certains paramètres : désactivation et mise en veille de certaines fonctionnalités, réduction de la fréquence ou de la tension d'alimentation. Afin d'optimiser cette modulation, les fabricants exposent ces fonctionnalités au niveau de l'interface avec le logiciel. Ainsi, les programmes (généralement les noyaux des OS) peuvent adapter le fonctionnement du processeur en fonction de leurs besoins. Certains travaux se sont intéressés à la menace que pouvaient représenter ces interfaces de configuration.

Tang *et al.* ont ainsi étudié les mécanismes de gestion d'énergie des processeurs ARM utilisés dans les smartphones [235]. Ils ont démontré qu'un module malveillant du noyau de l'OS pouvait manipuler la gestion dynamique de la fréquence afin de provoquer des fautes. En fait, la fonctionnalité matérielle expose des paramètres de configuration et ne vérifie pas que ces paramètres appartiennent à la zone de fonctionnement nominale du processeur. Ainsi, les auteurs ont réussi à extraire des clés stockées dans la partie isolée par TrustZone. Ils ont également pu charger un programme auto-signé dans le *secure world*. Cette approche a été reprise dans VoltJockey [236] qui se focalise sur la manipulation de la valeur de la tension au lieu de faire varier la fréquence. L'attaque est ainsi plus furtive et difficile à prévenir. Les auteurs ont aussi démontré que cette attaque pouvait être réalisée sur les processeurs Intel contre SGX [237].

Murdock *et al.* ont démontré qu'une attaque similaire pouvait être réalisée sur les plate-formes Intel pour contourner l'isolation fournie par SGX et faire fuir des données confidentielles de l'enclave [238]. Contrairement aux attaques par martellement de la mémoire, présentées dans la section suivante, cette injection de faute cible le processeur et non la mémoire. Ainsi le chiffrement de la mémoire réalisé par SGX ne permet pas de lutter contre cette attaque.
### 2.2.3 Attaques logicielles par injection de fautes

Des attaques logicielles par injection de fautes matérielles ont également été mises en évidence dans la littérature. Il s'agit de provoquer une altération d'une grandeur physique qui va provoquer une erreur dans le matériel (par exemple le changement d'une valeur dans la mémoire) qui *in fine* conduira à une défaillance des mécanismes de protection du processeur. Contrairement aux injections de fautes par attaques physiques, la faute est provoquée uniquement par l'exécution d'un programme, ce qui permet de les réaliser potentiellement à distance.

Nous détaillons ici les travaux relatifs à deux types d'injections de fautes par attaques logicielles, qui ont été mis en évidence récemment : les attaques exploitant la gestion de l'énergie (section 2.2.3.1) et les attaques par martellement de la mémoire (*rowhammer*), présentées en section 2.2.3.2.

#### 2.2.3.1 Exploitation logicielle de la gestion de l'énergie

Afin d'optimiser la gestion de la consommation d'électricité, les processeurs disposent de fonctionnalités de gestion dynamique de l'énergie. L'objectif est d'adapter au mieux la consommation énergétique en fonction de la demande, c'est-à-dire de la charge du processeur. Cette fonctionnalité est notamment cruciale pour les systèmes embarqués, les ordinateurs portables ou les *smartphone* alimentés sur batterie. Elle est également liée à la gestion de la dissipation énergétique et de la température du processeur.

Afin de moduler cette consommation énergétique, le processeur peut moduler certains paramètres : désactivation et mise en veille de certaines fonctionnalités, réduction de la fréquence ou de la tension d'alimentation. Afin d'optimiser cette modulation, les fabricants exposent ces fonctionnalités au niveau de l'interface avec le logiciel. Ainsi, les programmes (généralement les noyaux des OS) peuvent adapter le fonctionnement du processeur en fonction de leurs besoins. Certains travaux se sont intéressés à la menace que pouvaient représenter ces interfaces de configuration.

Tang *et al.* ont ainsi étudié les mécanismes de gestion d'énergie des processeurs ARM utilisés dans les smartphones [235]. Ils ont démontré qu'un module malveillant du noyau de l'OS pouvait manipuler la gestion dynamique de la fréquence afin de provoquer des fautes. En fait, la fonctionnalité matérielle expose des paramètres de configuration et ne vérifie pas que ces paramètres appartiennent à la zone de fonctionnement nominale du processeur. Ainsi, les auteurs ont réussi à extraire des clés stockées dans la partie isolée par TrustZone. Ils ont également pu charger un programme auto-signé dans le *secure world*. Cette approche a été reprise dans VoltJockey [236] qui se focalise sur la manipulation de la valeur de la tension au lieu de faire varier la fréquence. L'attaque est ainsi plus furtive et difficile à prévenir. Les auteurs ont aussi démontré que cette attaque pouvait être réalisée sur les processeurs Intel contre SGX [237].

Murdock *et al.* ont démontré qu'une attaque similaire pouvait être réalisée sur les plate-formes Intel pour contourner l'isolation fournie par SGX et faire fuir des données confidentielles de l'enclave [238]. Contrairement aux attaques par martellement de la mémoire, présentées dans la section suivante, cette injection de faute cible le processeur et non la mémoire. Ainsi le chiffrement de la mémoire réalisé par SGX ne permet pas de lutter contre cette attaque.
Kenjar et al. ont réalisé des travaux similaires. Ils s'attaquent toutefois plus spécifiquement aux instructions de calcul vectoriel et ont également mis en évidence des atteintes à l'intégrité permettant de contrôler le flot d'exécution [239] au sein d'une enclave SGX. Face à ces attaques, Intel a notamment publié une mise à jour du firmware UEFI permettant de désactiver certaines fonctionnalités de gestion de l'énergie.

### 2.2.3.2 Attaques par martellement de la mémoire

Contrairement aux attaques présentées dans les sections précédentes, Rowhammer est une attaque par injection de fautes contre la DRAM. Cette attaque exploite une vulnérabilité liée à la conception des circuits intégrés de DRAM. Ce type de mémoire repose essentiellement sur des cellules permettant de stocker un bit d'information à l'aide d'un condensateur et d'un transistor. L'état du condensateur (chargé ou déchargé) permet de représenter l'état de la cellule. Toutefois, le condensateur se décharge en raison de couvrants de fuite. Il est donc nécessaire de rafraîchir régulièrement l'état des cellules afin de recharger les condensateurs. Ces cellules sont organisées sous la forme d'une matrice. Les différents bits d'une même adresse mémoire sont en fait répartis sur plusieurs lignes. La lecture de ces lignes est destructive et nécessite de recharger l'état des cellules de la ligne.

L'attaque résulte de l'optimisation de cette technologie. Afin de proposer des quantités de mémoire plus importantes, les constructeurs ont augmenté la densité de cellules dans leurs circuits intégrés. Cela conduit à des cellules de plus en plus petites et de plus faible capacité. Ces circuits sont donc de plus en plus sujets aux perturbations électromagnétiques qui peuvent modifier l'état d'une cellule. L'attaque consiste à autogénérer ces perturbations en effectuant des lectures répétées de la mémoire. Ces lectures génèrent des signaux électriques pour l'activation des lignes de mémoire correspondant à l'adresse lue. Des lectures fréquentes provoquent une perturbation électromagnétique qui peut influencer l'état de cellules adjacentes. Plus précisément, ces signaux accélèrent la décharge des condensateurs. Si cette décharge est plus rapide que la période de rafraîchissement de l'état de la cellule, une erreur se produit et l'état de la cellule est modifié.

Ce phénomène était suspecté par les fabricants mais des chercheurs ont démontré qu'il pouvait effectivement être provoqué par l'exécution d'un programme [240], sans pour autant fournir d'attaque exploitant ce phénomène. Par la suite, des chercheurs de Google ont démontré des attaques permettant de contourner les mécanismes d'isolation du processeur [241].

Gruss et al. ont démontré que ce type d'attaque pouvait être réalisé depuis un programme JavaScript exécuté dans le navigateur, ce qui permet une exploitation à distance, si l'attquant parvient à convaincre la victime de naviguer sur un site malveillant [242]. Bosman et al. combinent une attaque Rowhammer avec une exploitation du mécanisme de déduplication des pages. Ces attaques leur donnent un accès arbitraire à la mémoire du processus du navigateur, en lecture et en écriture, depuis du code JavaScript [243]. Razavi et al. montrent qu'une évolution de cette attaque permet en outre d'accéder à l'intégralité de la mémoire physique [244].

Xiao et al. ont démontré qu'une attaque de type Rawhammer pouvait être réalisée entre différentes machines virtuelles afin de contourner l'isolation assurée par l'hyperviseur Xen [245]. Van der Veen et al. ont confirmé que cette attaque est également possible sur les smartphones utilisant une architecture ARM [246].
Kenjar et al. ont réalisé des travaux similaires. Ils s'attaquent toutefois plus spécifiquement aux instructions de calcul vectoriel et ont également mis en évidence des atteintes à l'intégrité permettant de contrôler le flot d'exécution [239] au sein d'une enclave SGX. Face à ces attaques, Intel a notamment publié une mise à jour du firmware UEFI permettant de désactiver certaines fonctionnalités de gestion de l'énergie.

### 2.2.3.2 Attaques par martellement de la mémoire

Contrairement aux attaques présentées dans les sections précédentes, Rowhammer est une attaque par injection de fautes contre la DRAM. Cette attaque exploite une vulnérabilité liée à la conception des circuits intégrés de DRAM. Ce type de mémoire repose essentiellement sur des cellules permettant de stocker un bit d'information à l'aide d'un condensateur et d'un transistor. L'état du condensateur (chargé ou déchargé) permet de représenter l'état de la cellule. Toutefois, le condensateur se décharge en raison de couvrants de fuite. Il est donc nécessaire de rafraîchir régulièrement l'état des cellules afin de recharger les condensateurs. Ces cellules sont organisées sous la forme d'une matrice. Les différents bits d'une même adresse mémoire sont en fait répartis sur plusieurs lignes. La lecture de ces lignes est destructive et nécessite de recharger l'état des cellules de la ligne.

L'attaque résulte de l'optimisation de cette technologie. Afin de proposer des quantités de mémoire plus importantes, les constructeurs ont augmenté la densité de cellules dans leurs circuits intégrés. Cela conduit à des cellules de plus en plus petites et de plus faible capacité. Ces circuits sont donc de plus en plus sujets aux perturbations électromagnétiques qui peuvent modifier l'état d'une cellule. L'attaque consiste à autogénérer ces perturbations en effectuant des lectures répétées de la mémoire. Ces lectures génèrent des signaux électriques pour l'activation des lignes de mémoire correspondant à l'adresse lue. Des lectures fréquentes provoquent une perturbation électromagnétique qui peut influencer l'état de cellules adjacentes. Plus précisément, ces signaux accélèrent la décharge des condensateurs. Si cette décharge est plus rapide que la période de rafraîchissement de l'état de la cellule, une erreur se produit et l'état de la cellule est modifié.

Ce phénomène était suspecté par les fabricants mais des chercheurs ont démontré qu'il pouvait effectivement être provoqué par l'exécution d'un programme [240], sans pour autant fournir d'attaque exploitant ce phénomène. Par la suite, des chercheurs de Google ont démontré des attaques permettant de contourner les mécanismes d'isolation du processeur [241].

Gruss et al. ont démontré que ce type d'attaque pouvait être réalisé depuis un programme JavaScript exécuté dans le navigateur, ce qui permet une exploitation à distance, si l'attacker parvient à convaincre la victime de naviguer sur un site malveillant [242]. Bosman et al. combinent une attaque Rowhammer avec une exploitation du mécanisme de déduplication des pages. Ces attaques leur donnent un accès arbitraire à la mémoire du processus du navigateur, en lecture et en écriture, depuis du code JavaScript [243]. Razavi et al. montrent qu'une évolution de cette attaque permet en outre d'accéder à l'intégralité de la mémoire physique [244].

Xiao et al. ont démontré qu'une attaque de type Rawhammer pouvait être réalisée entre différentes machines virtuelles afin de contourner l'isolation assurée par l'hyperviseur Xen [245]. Van der Veen et al. ont confirmé que cette attaque est également possible sur les smartphones utilisant une architecture ARM [246].
Différents mécanismes de protections ont été proposés pour contrer les précédentes attaques. Gruss et al. ont toutefois démontré que ces contre-mesures pouvaient être contournées et qu'il était possible de réaliser des attaques Rawhammer furtives depuis une enclave SGX, permettant de réaliser des escalades de privilèges [247].

Cette attaque représente une vulnérabilité sérieuse. Cojocar et al. ont proposé une méthodologie permettant à des fournisseurs de cloud computing d'évaluer si leur infrastructure est vulnérable à ce type d'attaque [248].

Plus récemment, Kwong et al. ont proposé une variante de l'attaque Rawhammer permettant de réaliser une attaque par canal auxiliaire. Cette attaque permet à un processus attaquant de faire fuir des données confidentielles d'un processus à partir du martellement de la mémoire du processus attaquant [249]. En effet, les auteurs démontrent qu'en observant les modifications de l'état des bits de sa propre mémoire, un attaquant peut en déduire l'état des lignes adjacentes de la DRAM.

### 2.2.4 Attaques contre les enclaves sécurisées

De nombreux travaux se sont intéressés à évaluer la sécurité des mécanismes d'enclaves présentés en section 2.1.4. Ces enclaves doivent faire face à deux types de vulnérabilités :

- le code exécuté dans l'enclave peut comprendre des vulnérabilités logicielles, notamment liées à la gestion de la mémoire;

- des vulnérabilités matérielles peuvent mettre en défaut l'isolation censée être assurée par le mécanisme d'enclave et permettre ainsi des attaques logicielles par canaux auxiliaires.

#### 2.2.4.1 Exploitation de vulnérabilités logicielles

Les enclaves et les TEE permettent d'isoler des fonctionnalités. Toutefois, le code exécuté dans ces environnements peut comporter des vulnérabilités logicielles. Initialement, l'objectif était d'exécuter des composants logiciels de taille restreinte et ayant un spectre fonctionnel réduit. Toutefois, en pratique, le code exécuté en enclave peut s'avérer relativement volumineux et s'appuyer sur des bibliothèques ou des systèmes d'exploitations (dans le cas des enclaves TrustZone, par exemple). En outre des environnements ont été proposés permettant d'exécuter l'intégralité d'une application dans une enclave (notamment pour SGX). La surface d'attaque peut devenir importante, de même que la TCB. L'exploitation de certaines de ces vulnérabilités peut remettre en cause l'isolation censée être assurée ou les fonctions de sécurité assurées par le code de l'enclave.

En outre, les enclaves telles que SGX ou Sanctum reposent en grande partie sur des services fournis par l'OS, comme l'ordonnancement des fils d'exécution ou la gestion de la paginpression. Le modèle d'attaquant est censé garantir que l'OS, qui n'est pas de confiance, ne peut corrompre le code exécuté en enclave. Toutefois, le contrôle qu'il exerce sur les applications exécutées dans l'enclave permet de réaliser ou de faciliter certaines attaques.

Ainsi, Weichbrodt et al. montrent que l'OS peut influencer l'ordonnancement des fils d'exécution et amplifier ainsi des vulnérabilités liées à la synchronisation des fils d'exécution de l'enclave [250]. Par exemple, ce type d'attaque permet de mettre en évidence ou d'amplifier des vulnérabilités de type use-after-free ou TOCTOU (Time-Of-Check
Différents mécanismes de protections ont été proposés pour contrer les précédentes attaques. Gruss et al. ont toutefois démontré que ces contre-mesures pouvaient être contournées et qu'il était possible de réaliser des attaques Rawhammer furtives depuis une enclave SGX, permettant de réaliser des escalades de privilèges [247].

Cette attaque représente une vulnérabilité sérieuse. Cojocar et al. ont proposé une méthodologie permettant à des fournisseurs de cloud computing d'évaluer si leur infrastructure est vulnérable à ce type d'attaque [248].

Plus récemment, Kwong et al. ont proposé une variante de l'attaque Rawhammer permettant de réaliser une attaque par canal auxiliaire. Cette attaque permet à un processus attaquant de faire fuir des données confidentielles d'un processus à partir du martellement de la mémoire du processus attaquant [249]. En effet, les auteurs démontrent qu'en observant les modifications de l'état des bits de sa propre mémoire, un attaquant peut en déduire l'état des lignes adjacentes de la DRAM.

### 2.2.4 Attaques contre les enclaves sécurisées

De nombreux travaux se sont intéressés à évaluer la sécurité des mécanismes d'enclaves présentés en section 2.1.4. Ces enclaves doivent faire face à deux types de vulnérabilités :

- le code exécuté dans l'enclave peut comprendre des vulnérabilités logicielles, notamment liées à la gestion de la mémoire;

- des vulnérabilités matérielles peuvent mettre en défaut l'isolation censée être assurée par le mécanisme d'enclave et permettre ainsi des attaques logicielles par canaux auxiliaires.

#### 2.2.4.1 Exploitation de vulnérabilités logicielles

Les enclaves et les TEE permettent d'isoler des fonctionnalités. Toutefois, le code exécuté dans ces environnements peut comporter des vulnérabilités logicielles. Initialement, l'objectif était d'exécuter des composants logiciels de taille restreinte et ayant un spectre fonctionnel réduit. Toutefois, en pratique, le code exécuté en enclave peut s'avérer relativement volumineux et s'appuyer sur des bibliothèques ou des systèmes d'exploitations (dans le cas des enclaves TrustZone, par exemple). En outre des environnements ont été proposés permettant d'exécuter l'intégralité d'une application dans une enclave (notamment pour SGX). La surface d'attaque peut devenir importante, de même que la TCB. L'exploitation de certaines de ces vulnérabilités peut remettre en cause l'isolation censée être assurée ou les fonctions de sécurité assurées par le code de l'enclave.

En outre, les enclaves telles que SGX ou Sanctum reposent en grande partie sur des services fournis par l'OS, comme l'ordonnancement des fils d'exécution ou la gestion de la paginpression. Le modèle d'attaquant est censé garantir que l'OS, qui n'est pas de confiance, ne peut corrompre le code exécuté en enclave. Toutefois, le contrôle qu'il exerce sur les applications exécutées dans l'enclave permet de réaliser ou de faciliter certaines attaques.

Ainsi, Weichbrodt et al. montrent que l'OS peut influencer l'ordonnancement des fils d'exécution et amplifier ainsi des vulnérabilités liées à la synchronisation des fils d'exécution de l'enclave [250]. Par exemple, ce type d'attaque permet de mettre en évidence ou d'amplifier des vulnérabilités de type use-after-free ou TOCTOU (Time-Of-Check
to Time-Of-Use). L'exploitation de ces vulnérabilités permet ensuite potentiellement de contourner des vérifications réalisées par le code de l'enclave.

Lee et al. s'intéressent à la réalisation d'attaques de type ROP, adaptées aux contraintes imposées par SGX. Ces attaques exploitent des vulnérabilités de corruption mémoire dans le code de l'enclave et forcent ce code à réveler des secrets, brisant ainsi les garanties d'isolation de l'enclave [251]. Biondo et al. étendent la portée de ce type d'attaques [252]. Leur approche permet de réaliser des attaques depuis l'espace utilisateur et malgré l'utilisation de l'ASLR dans l'enclave SGX.

Cloosters et al. ont développé l'outil TeeRex qui permet d'automatiser l'analyse de vulnérabilités du code binaire des applications exécutées dans les enclaves SGX [253]. Les auteurs ont appliqué leur outil avec succès sur plusieurs codes d'enclaves, notamment ceux développés par Intel et Baidu, ce qui leur a permis d'identifier des vulnérabilités dans ces logiciels.

Van Bulck et al. s'intéressent à la sécurité des environnements permettant d'exécuter des composants logiciels au sein d'une enclave [254]. Leur étude porte sur différents types d'environnements, qu'il s'agisse de SDK comme ceux fournis par Intel [77], Microsoft [78] ou Google [79] pour exécuter des fonctions au sein d'une enclave SGX ou d'environnements plus complexes de type *library OS* comme Graphene [85] ou SGX-LKL [83], qui permettent d'exécuter une application complète dans l'enclave SGX. Ils s'intéressent également à Keystone [91] (enclave RISC-V) ou Sancus [52] (TEE pour système embarqué). Ils ont révélé la présence de vulnérabilités au niveau des interfaces de ces systèmes avec le code non isolé de l'application. Ils soulignent le fait que ces environnements représentent une surface d'attaque importante. En outre, le filtrage que ces environnements sont censés mettre en œuvre est imparfait. Le filtrage des points d'entrées, situé dans l'interface avec le code non isolé, doit faire l'objet d'une attention particulière.

Machiry et al. s'intéressent aux vulnérabilités des TEE TrustZone et de leurs implications pour le système exécuté dans le *Normal World* [255]. Ils démontrent qu'un attaquant peut exploiter l'accès privilégié des applications exécutées dans le TEE. En effet, ces applications ont également accès à l'intégralité de la mémoire des applications et de l'OS exécuté dans le *Normal World*, sachant que l'inverse n'est pas vrai. Ainsi, un attaquant peut utiliser une application du TEE pour accéder à la mémoire d'une autre application exécutée dans le *Normal World*, en exploitant une forme de *confused deputy attack*. Ils ont pu vérifier la faisabilité de ce type d'attaques sur plusieurs TEE disponibles sur le marché dont OP-TEE, QSEE et le TEE développé par Huawei.

Une approche similaire [256] a été développée par Suciu et al. . Toutefois, ces travaux ne supposent pas la présence de vulnérabilités dans une application sécurisée. Les auteurs ont en outre développé un outil leur permettant d'automatiser la recherche de vulnérabilités dans les applications sécurisées. Ils ont ainsi pu identifier 19 vulnérabilités parmi les applications sécurisées de trois TEE (Kinibi, QSEE, et Teegris). L'exploitation de ces vulnérabilités permet à des applications du *Normal World* d'obtenir des données appartenant à d'autres applications.

Di Shen présente également comment Knox, la solution de Samsung permettant de vérifier l'intégrité du noyau Linux, peut être contournée afin d'exploiter une vulnérabilité dans le noyau et *in fine* obtenir les droits root sur le téléphone [257]. Les ingénieurs de la société Quarkslab ont également identifié plusieurs vulnérabilités dans Kinibi, le TEE développé
to Time-Of-Use). L'exploitation de ces vulnérabilités permet ensuite potentiellement de contourner des vérifications réalisées par le code de l'enclave.

Lee et al. s'intéressent à la réalisation d'attaques de type ROP, adaptées aux contraintes imposées par SGX. Ces attaques exploitent des vulnérabilités de corruption mémoire dans le code de l'enclave et forcent ce code à réveler des secrets, brisant ainsi les garanties d'isolation de l'enclave [251]. Biondo et al. étendent la portée de ce type d'attaques [252]. Leur approche permet de réaliser des attaques depuis l'espace utilisateur et malgré l'utilisation de l'ASLR dans l'enclave SGX.

Cloosters et al. ont développé l'outil TeeRex qui permet d'automatiser l'analyse de vulnérabilités du code binaire des applications exécutées dans les enclaves SGX [253]. Les auteurs ont appliqué leur outil avec succès sur plusieurs codes d'enclaves, notamment ceux développés par Intel et Baidu, ce qui leur a permis d'identifier des vulnérabilités dans ces logiciels.

Van Bulck et al. s'intéressent à la sécurité des environnements permettant d'exécuter des composants logiciels au sein d'une enclave [254]. Leur étude porte sur différents types d'environnements, qu'il s'agisse de SDK comme ceux fournis par Intel [77], Microsoft [78] ou Google [79] pour exécuter des fonctions au sein d'une enclave SGX ou d'environnements plus complexes de type *library OS* comme Graphene [85] ou SGX-LKL [83], qui permettent d'exécuter une application complète dans l'enclave SGX. Ils s'intéressent également à Keystone [91] (enclave RISC-V) ou Sancus [52] (TEE pour système embarqué). Ils ont révélé la présence de vulnérabilités au niveau des interfaces de ces systèmes avec le code non isolé de l'application. Ils soulignent le fait que ces environnements représentent une surface d'attaque importante. En outre, le filtrage que ces environnements sont censés mettre en œuvre est imparfait. Le filtrage des points d'entrées, situé dans l'interface avec le code non isolé, doit faire l'objet d'une attention particulière.

Machiry et al. s'intéressent aux vulnérabilités des TEE TrustZone et de leurs implications pour le système exécuté dans le *Normal World* [255]. Ils démontrent qu'un attaquant peut exploiter l'accès privilégié des applications exécutées dans le TEE. En effet, ces applications ont également accès à l'intégralité de la mémoire des applications et de l'OS exécuté dans le *Normal World*, sachant que l'inverse n'est pas vrai. Ainsi, un attaquant peut utiliser une application du TEE pour accéder à la mémoire d'une autre application exécutée dans le *Normal World*, en exploitant une forme de *confused deputy attack*. Ils ont pu vérifier la faisabilité de ce type d'attaques sur plusieurs TEE disponibles sur le marché dont OP-TEE, QSEE et le TEE développé par Huawei.

Une approche similaire [256] a été développée par Suciu et al. . Toutefois, ces travaux ne supposent pas la présence de vulnérabilités dans une application sécurisée. Les auteurs ont en outre développé un outil leur permettant d'automatiser la recherche de vulnérabilités dans les applications sécurisées. Ils ont ainsi pu identifier 19 vulnérabilités parmi les applications sécurisées de trois TEE (Kinibi, QSEE, et Teegris). L'exploitation de ces vulnérabilités permet à des applications du *Normal World* d'obtenir des données appartenant à d'autres applications.

Di Shen présente également comment Knox, la solution de Samsung permettant de vérifier l'intégrité du noyau Linux, peut être contournée afin d'exploiter une vulnérabilité dans le noyau et *in fine* obtenir les droits root sur le téléphone [257]. Les ingénieurs de la société Quarkslab ont également identifié plusieurs vulnérabilités dans Kinibi, le TEE développé
par Trustonic et utilisé sur certains téléphones Samsung [258].

Wang et al. s'intéressent plus particulièrement à la sécurité des *Isolated Execution Environments* [259]. Ces environnements sont des enclaves qui s'exécutent dans le *Normal World* mais qui sont isolées des autres applications et de l'OS, grâce à un moniteur de sécurité qui s'exécute dans le *Secure World*. Cette approche est notamment mise en œuvre par TrustICE [67] et SANCTUARY [68], présentés en section 2.1.4.1. Elle vise à répondre aux limitations de déploiement des applications dans TrustZone. Toutefois, les auteurs montrent que ces solutions sont vulnérables à des attaques visant le cache, qui n'est pas protégé, contrairement aux applications s'exécutant au sein de TrustZone.

Ces attaques sont différentes des attaques par canaux auxiliaires utilisant le cache. Elles exploitent le fait que l'attaquant maîtrise l'OS et notamment le mécanisme de pagination. Un module noyau malveillant peut donc configurer une page mémoire pour qu'elle correspondbe à des adresses physiques utilisées par une enclave. Même si le moniteur empêche l'accès à la mémoire, l'attaquant peut lire les données présentes dans le cache.

### 2.2.4.2 Attaques par canaux auxiliaires contre les enclaves

De nombreux travaux ont démontré que l'isolation fournie par les mécanismes d'enclaves n'était en général pas robuste aux attaques par canaux auxiliaires. Ce résultat est, pour certaines enclaves (notamment SGX), attendu car elles ne prennent pas en compte ce type de menaces dans leur modèle d'attaquant.

Xu et al. présentent un nouveau type d'attaques par canal auxiliaire, les *controlled-channel attacks*, qui s'appliquent aux mécanismes de TEE (notamment SGX) qui s'appuient sur les services de l'OS (gestion des interruptions, de la pagination, de l'ordonnancement, etc.) [260]. Habituellement, dans les attaques par canaux auxiliaires, on ne suppose pas que l'OS soit sous le contrôle de l'attaquant. Il est donc source de bruit qu'il faut filtrer. Dans le contexte des enclaves, l'OS est supposé potentiellement malveillant. Dès lors, il est possible de construire des attaques par canaux auxiliaires très précises, sans bruit lié à l'OS. Les auteurs utilisent le mécanisme de défaut de page pour mettre en place leur attaque. Ils ont notamment appliqué cette attaque à Haven [82], qui est un environnement d'exécution de type *library OS* pour SGX.

Toutefois, des contre-mesures logicielles sont possibles pour se prémunir des attaques précédentes qui exploitent les défauts de page. Moghimi et al. utilisent une attaque de type PRIME+PROBE, qui exploite les accès au cache, et démontrent que la maîtrise de l'OS permet à l'attaquant de réaliser des attaques par canaux auxiliaires [261]. Ces attaques permettent de suivre tous les accès mémoire réalisés par le code de l'enclave avec une grande précision. De même, Van Bulck et al. utilisent d'autres formes de canaux auxiliaires issus de la traduction d'adresse, qui ne génèrent pas de défaut de page et ne sont pas protégés par les contre-mesures logicielles [262]. Wang et al. dressent un bilan de ces différents travaux et réalisent une analyse détaillée des vulnérabilités potentielles de SGX par rapport à ce type d'attaque et de la robustesse des contre-mesures proposées jusqu'à présent [263]. Ils proposent de nouvelles attaques et montrent que les contre-mesures proposées ne permettent pas de lutter efficacement contre ces attaques.

Plus récemment, Moghimi et al. ont démontré qu'il était possible de diminuer la granularité des *controlled-channel attacks* utilisant le défaut de page en exécutant les applications en pas-à-pas [264].
par Trustonic et utilisé sur certains téléphones Samsung [258].

Wang et al. s'intéressent plus particulièrement à la sécurité des *Isolated Execution Environments* [259]. Ces environnements sont des enclaves qui s'exécutent dans le *Normal World* mais qui sont isolées des autres applications et de l'OS, grâce à un moniteur de sécurité qui s'exécute dans le *Secure World*. Cette approche est notamment mise en œuvre par TrustICE [67] et SANCTUARY [68], présentés en section 2.1.4.1. Elle vise à répondre aux limitations de déploiement des applications dans TrustZone. Toutefois, les auteurs montrent que ces solutions sont vulnérables à des attaques visant le cache, qui n'est pas protégé, contrairement aux applications s'exécutant au sein de TrustZone.

Ces attaques sont différentes des attaques par canaux auxiliaires utilisant le cache. Elles exploitent le fait que l'attaquant maîtrise l'OS et notamment le mécanisme de pagination. Un module noyau malveillant peut donc configurer une page mémoire pour qu'elle correspondbe à des adresses physiques utilisées par une enclave. Même si le moniteur empêche l'accès à la mémoire, l'attaquant peut lire les données présentes dans le cache.

### 2.2.4.2 Attaques par canaux auxiliaires contre les enclaves

De nombreux travaux ont démontré que l'isolation fournie par les mécanismes d'enclaves n'était en général pas robuste aux attaques par canaux auxiliaires. Ce résultat est, pour certaines enclaves (notamment SGX), attendu car elles ne prennent pas en compte ce type de menaces dans leur modèle d'attaquant.

Xu et al. présentent un nouveau type d'attaques par canal auxiliaire, les *controlled-channel attacks*, qui s'appliquent aux mécanismes de TEE (notamment SGX) qui s'appuient sur les services de l'OS (gestion des interruptions, de la pagination, de l'ordonnancement, etc.) [260]. Habituellement, dans les attaques par canaux auxiliaires, on ne suppose pas que l'OS soit sous le contrôle de l'attaquant. Il est donc source de bruit qu'il faut filtrer. Dans le contexte des enclaves, l'OS est supposé potentiellement malveillant. Dès lors, il est possible de construire des attaques par canaux auxiliaires très précises, sans bruit lié à l'OS. Les auteurs utilisent le mécanisme de défaut de page pour mettre en place leur attaque. Ils ont notamment appliqué cette attaque à Haven [82], qui est un environnement d'exécution de type *library OS* pour SGX.

Toutefois, des contre-mesures logicielles sont possibles pour se prémunir des attaques précédentes qui exploitent les défauts de page. Moghimi et al. utilisent une attaque de type PRIME+PROBE, qui exploite les accès au cache, et démontrent que la maîtrise de l'OS permet à l'attaquant de réaliser des attaques par canaux auxiliaires [261]. Ces attaques permettent de suivre tous les accès mémoire réalisés par le code de l'enclave avec une grande précision. De même, Van Bulck et al. utilisent d'autres formes de canaux auxiliaires issus de la traduction d'adresse, qui ne génèrent pas de défaut de page et ne sont pas protégés par les contre-mesures logicielles [262]. Wang et al. dressent un bilan de ces différents travaux et réalisent une analyse détaillée des vulnérabilités potentielles de SGX par rapport à ce type d'attaque et de la robustesse des contre-mesures proposées jusqu'à présent [263]. Ils proposent de nouvelles attaques et montrent que les contre-mesures proposées ne permettent pas de lutter efficacement contre ces attaques.

Plus récemment, Moghimi et al. ont démontré qu'il était possible de diminuer la granularité des *controlled-channel attacks* utilisant le défaut de page en exécutant les applications en pas-à-pas [264].
Lee *et al.* ont proposé un autre type de canal caché visant les enclaves SGX [265]. Ils utilisent le *Last Branch Record*, un mécanisme fourni par les processeurs Intel afin de tracer les derniers branchements pris par un programme. Cette fonctionnalité a été introduite pour des besoins de profilage des applications. Malheureusement, ce buffer n’est pas nettoyé lors de la sortie d’une enclave SGX. Les auteurs ont démontré que ce mécanisme pouvait être utilisé pour réaliser une attaque par canaux auxiliaires qui révèle des informations sur le flot de contrôle du code de l’enclave. Les auteurs ont ainsi pu récupérer une clé RSA manipulée par le code de l’enclave.

Van Bulck *et al.* ont proposé NEMESIS [266], un nouveau type d'attaque par canal auxiliaire utilisant le temps nécessaire au traitement des interruptions dans le processeur. Le mécanisme utilise le même phénomène qui est exploité dans les attaques de type Meltdown. Toutefois, il ne s'agit pas ici de tirer profit de l'exécution transitoire des instructions qui en découle mais de mesurer le temps pris par le traitement des interruptions, afin d'inférer l'état de la microarchitecture dans l'enclave. Les auteurs ont notamment appliqué leurs travaux à SGX et Sancus [52].

Toutes les attaques par canaux auxiliaires contre les enclaves SGX, présentées précédemment, nécessitent la présence d'un code vulnérable qui réalise des accès mémoire en fonction de la valeur d'un secret. Wang *et al.* ont proposé une approche permettant d'identifier automatiquement les attaques par canaux auxiliaires qu'il est possible d'utiliser à partir de l'analyse dynamique du code binaire exécuté dans l'enclave [267].

Des attaques exploitant l'exécution transitoire ont également été démontrées contre SGX.

Les auteurs de NEMESIS ont par la suite proposé Foreshadow [268], une attaque exploitant l'exécution transitoire et permettant de faire fuir les données d'une enclave se trouvant dans le cache L1 du processeur vers un processus utilisateur. Il s'agit d'une variante des vulnérabilités de type Meltdown [217]. Contrairement aux attaques précédentes, cette attaque ne suppose pas la présence d'un code vulnérable dans l'enclave. Les auteurs ont notamment pu la mettre en œuvre pour récupérer la clé privée utilisée par le mécanisme d'attestation à distance de SGX.

Chen *et al.* ont également proposé des attaques de type Spectre qui exploitent des gadgets présents dans la plupart des environnements d'exécution pour SGX [269].

Des attaques par canaux auxiliaires ont également été mis en évidence contre les TEE protégés par TrustZone.

Lapid *et al.* ont ainsi démontré que l'implémentation AES utilisée dans l'application Keymaster du TEE Kinibi, utilisée sur certains téléphones Samsung, était vulnérable à une attaque par canaux auxiliaires utilisant le cache [270].

Cho *et al.* ont proposé Prime+Count [271], un nouveau type de canal caché entre une application sécurisée et le Normal World, qui utilise le cache partagé entre les deux mondes TrustZone. L'objectif est de pouvoir contourner les mécanismes de sécurité qui ont été ajoutés afin de filtrer les messages provenant du Normal World et d'authentifier les applications qui peuvent légitimement envoyer ces messages et communiquer avec le Secure World [65].
Lee *et al.* ont proposé un autre type de canal caché visant les enclaves SGX [265]. Ils utilisent le *Last Branch Record*, un mécanisme fourni par les processeurs Intel afin de tracer les derniers branchements pris par un programme. Cette fonctionnalité a été introduite pour des besoins de profilage des applications. Malheureusement, ce buffer n’est pas nettoyé lors de la sortie d’une enclave SGX. Les auteurs ont démontré que ce mécanisme pouvait être utilisé pour réaliser une attaque par canaux auxiliaires qui révèle des informations sur le flot de contrôle du code de l’enclave. Les auteurs ont ainsi pu récupérer une clé RSA manipulée par le code de l’enclave.

Van Bulck *et al.* ont proposé NEMESIS [266], un nouveau type d'attaque par canal auxiliaire utilisant le temps nécessaire au traitement des interruptions dans le processeur. Le mécanisme utilise le même phénomène qui est exploité dans les attaques de type Meltdown. Toutefois, il ne s'agit pas ici de tirer profit de l'exécution transitoire des instructions qui en découle mais de mesurer le temps pris par le traitement des interruptions, afin d'inférer l'état de la microarchitecture dans l'enclave. Les auteurs ont notamment appliqué leurs travaux à SGX et Sancus [52].

Toutes les attaques par canaux auxiliaires contre les enclaves SGX, présentées précédemment, nécessitent la présence d'un code vulnérable qui réalise des accès mémoire en fonction de la valeur d'un secret. Wang *et al.* ont proposé une approche permettant d'identifier automatiquement les attaques par canaux auxiliaires qu'il est possible d'utiliser à partir de l'analyse dynamique du code binaire exécuté dans l'enclave [267].

Des attaques exploitant l'exécution transitoire ont également été démontrées contre SGX.

Les auteurs de NEMESIS ont par la suite proposé Foreshadow [268], une attaque exploitant l'exécution transitoire et permettant de faire fuir les données d'une enclave se trouvant dans le cache L1 du processeur vers un processus utilisateur. Il s'agit d'une variante des vulnérabilités de type Meltdown [217]. Contrairement aux attaques précédentes, cette attaque ne suppose pas la présence d'un code vulnérable dans l'enclave. Les auteurs ont notamment pu la mettre en œuvre pour récupérer la clé privée utilisée par le mécanisme d'attestation à distance de SGX.

Chen *et al.* ont également proposé des attaques de type Spectre qui exploitent des gadgets présents dans la plupart des environnements d'exécution pour SGX [269].

Des attaques par canaux auxiliaires ont également été mis en évidence contre les TEE protégés par TrustZone.

Lapid *et al.* ont ainsi démontré que l'implémentation AES utilisée dans l'application Keymaster du TEE Kinibi, utilisée sur certains téléphones Samsung, était vulnérable à une attaque par canaux auxiliaires utilisant le cache [270].

Cho *et al.* ont proposé Prime+Count [271], un nouveau type de canal caché entre une application sécurisée et le Normal World, qui utilise le cache partagé entre les deux mondes TrustZone. L'objectif est de pouvoir contourner les mécanismes de sécurité qui ont été ajoutés afin de filtrer les messages provenant du Normal World et d'authentifier les applications qui peuvent légitimement envoyer ces messages et communiquer avec le Secure World [65].
## 2.2.5 Rétroconception de la microarchitecture

La mise au point des attaques contre la microarchitecture nécessite bien souvent de connaître précisément les détails d'implémentation. Toutefois, ces détails sont souvent peu documentés car ils font partie des secrets industriels des constructeurs. Il faut donc dans ce cas réaliser une étape de rétroconception ou de modélisation de cette microarchitecture.

### 2.2.5.1 Modélisation et évaluation des attaques contre la microarchitecture

Un certain nombre de travaux se sont intéressés à développer des outils permettant d'analyser les attaques contre la microarchitecture afin de mieux les comprendre et d'obtenir des éléments quantitatifs sur ces attaques, par exemple sur le nombre d'instructions qu'il est possible d'exécuter de manière transitoire.

Zhang et al. ont notamment proposé un outil permettant d'analyser les attaques par canaux auxiliaires contre les caches [272]. L'outil permet d'analyser différentes techniques (Prime-Probe, Evict-Time, Flush-Reload, Flush-Flush, Prime-Abort) et d'évaluer les performances des contre-mesures. Pour cela, les auteurs utilisent des techniques d'apprentissage à base de réseau de neurones.

Abel et al. ont développé uops.info [273], un outil permettant de construire des modèles fiables de la latence, du débit et de l'utilisation des ports des unités d'exécution pour les instructions de l'architecture x86. Cet outil a été développé à des fins d'optimisation de code mais il peut fournir des informations intéressantes pour le développement d'attaques contre la microarchitecture.

Xiao et al. ont proposé SPEECHMINER, un outil permettant d'analyser les attaques exploitant l'exécution transitoire [274]. Leur approche regroupe dans un même outil différents tests permettant d'évaluer différents types d'attaques et de les mesurer.

### 2.2.5.2 Rétroconception et modélisation des caches

Les attaques par canaux auxiliaires utilisant le cache nécessitent de connaître précisément l'organisation de la hiérarchie des différents niveaux de caches, sur une microarchitecture donnée.

Ainsi Abel et al. ont réalisé une étude sur les politiques de remplacement des caches à l'aide d'un microbenchmarck développé spécifiquement [275]. Cette étude a été réalisée dans l'objectif de modéliser les performances des systèmes mais ce type d'approche fournit des informations intéressantes pour la sécurité.

Maurice et al. ont réalisé la rétroconception de l'adressage du LLC des processeurs à l'aide des compteurs de performances [276]. Cette technique est nécessaire car l'adressage des LLC fait maintenant appel à des fonctions complexes et non documentées.

Green et al. ont révélé la présence d'AutoLock [277], un mécanisme présent sur certains SoC ARM qui améliore les performances des caches mais peut gêner la réalisation des attaques par canaux auxiliaires. Cette fonctionnalité n'était pas documentée publiquement et les auteurs ont du rétroconcevoir cette fonctionnalité. Ils documentent la fonctionnalité
## 2.2.5 Rétroconception de la microarchitecture

La mise au point des attaques contre la microarchitecture nécessite bien souvent de connaître précisément les détails d'implémentation. Toutefois, ces détails sont souvent peu documentés car ils font partie des secrets industriels des constructeurs. Il faut donc dans ce cas réaliser une étape de rétroconception ou de modélisation de cette microarchitecture.

### 2.2.5.1 Modélisation et évaluation des attaques contre la microarchitecture

Un certain nombre de travaux se sont intéressés à développer des outils permettant d'analyser les attaques contre la microarchitecture afin de mieux les comprendre et d'obtenir des éléments quantitatifs sur ces attaques, par exemple sur le nombre d'instructions qu'il est possible d'exécuter de manière transitoire.

Zhang et al. ont notamment proposé un outil permettant d'analyser les attaques par canaux auxiliaires contre les caches [272]. L'outil permet d'analyser différentes techniques (Prime-Probe, Evict-Time, Flush-Reload, Flush-Flush, Prime-Abort) et d'évaluer les performances des contre-mesures. Pour cela, les auteurs utilisent des techniques d'apprentissage à base de réseau de neurones.

Abel et al. ont développé uops.info [273], un outil permettant de construire des modèles fiables de la latence, du débit et de l'utilisation des ports des unités d'exécution pour les instructions de l'architecture x86. Cet outil a été développé à des fins d'optimisation de code mais il peut fournir des informations intéressantes pour le développement d'attaques contre la microarchitecture.

Xiao et al. ont proposé SPEECHMINER, un outil permettant d'analyser les attaques exploitant l'exécution transitoire [274]. Leur approche regroupe dans un même outil différents tests permettant d'évaluer différents types d'attaques et de les mesurer.

### 2.2.5.2 Rétroconception et modélisation des caches

Les attaques par canaux auxiliaires utilisant le cache nécessitent de connaître précisément l'organisation de la hiérarchie des différents niveaux de caches, sur une microarchitecture donnée.

Ainsi Abel et al. ont réalisé une étude sur les politiques de remplacement des caches à l'aide d'un microbenchmarck développé spécifiquement [275]. Cette étude a été réalisée dans l'objectif de modéliser les performances des systèmes mais ce type d'approche fournit des informations intéressantes pour la sécurité.

Maurice et al. ont réalisé la rétroconception de l'adressage du LLC des processeurs à l'aide des compteurs de performances [276]. Cette technique est nécessaire car l'adressage des LLC fait maintenant appel à des fonctions complexes et non documentées.

Green et al. ont révélé la présence d'AutoLock [277], un mécanisme présent sur certains SoC ARM qui améliore les performances des caches mais peut gêner la réalisation des attaques par canaux auxiliaires. Cette fonctionnalité n'était pas documentée publiquement et les auteurs ont du rétroconcevoir cette fonctionnalité. Ils documentent la fonctionnalité
et fournissent des méthodes permettant de tester si la fonctionnalité est présente sur un SoC donné.

Youngjoo et al. proposent une méthodologie permettant d'identifier des attaques par canal caché pour une implémentation donnée d'un algorithme [278]. L'approche développée a permis aux auteurs d'identifier un nouveau type d'attaque par canal caché exploitant les accès réalisés par le Instruction Pointer-based stride prefetcher. Cet élément de la microarchitecture des processeurs Intel va inférer les adresses des prochaines instructions afin de précharger le cache avec les instructions en question.

Les attaques par canal caché utilisant le LLC reposent généralement sur la capacité de l'attaquant à pouvoir évincer les différentes lignes d'un ensemble de ce cache. Cela nécessite pour l'attaquant de pouvoir déterminer des ensembles minimaux d'éviction. Il s'agit d'ensembles d'adresses virtuelles qui, lorsqu'on réalise des accès en lecture à chacune des adresses qui les composent, permettent d'évincer complètement un ensemble donné du cache. Calculer explicitement cet ensemble est difficile, d'autant que l'adressage du LLC utilise les adresses physiques et que l'attaquant ne dispose pas toujours des privilèges du noyau lui permettant de retrouver la correspondance entre adresses virtuelles et physiques. Song et al. proposent donc des heuristiques pour déterminer ces ensembles [279]. Ils montrent que leur approche permet de construire ces ensembles plus rapidement que prévu.

Kurth et al. ont réalisé la rétroconception du DCA (Direct Cache Access) pour les processeurs Intel [280]. Cette fonctionnalité permet aux périphériques de réaliser des accès directement dans le LLC, ce qui améliore sensiblement les performances. Toutefois, les auteurs montrent que ce mécanisme peut être utilisé pour réaliser une attaque par canaux auxiliaires utilisant un périphérique. Ils montrent notamment qu'une carte réseau peut réaliser des attaques de type PRIME+PROBE.

### 2.2.5.3 Rétroconception et modélisation de la mémoire

Des travaux de rétroconception ont également été réalisés sur l'organisation de la mémoire à différents niveaux.

Pessl et al. ont notamment réalisé un travail de rétroconception pour modéliser l'organisation de la mémoire physique sur un ordinateur disposant de plusieurs processeurs [281]. Sur ce type de configuration, l'exploitation d'un canal caché utilisant le cache n'est pas possible car la victime est souvent localisée sur un processeur différent de celui utilisé par l'attaquant. Les auteurs montrent qu'un canal auxiliaire utilisant le DRAM row buffer, qui est partagé entre les différents processeurs, est possible. Pour cela ils proposent deux techniques pour rétroconcevoir l'association d'une adresse mémoire avec la mémoire physique, afin de déterminer notamment les channel, rank et bank correspondant à une adresse.

De même, Tatar et al. ont développé RAMSES [282], un outil permettant de modéliser la correspondance entre les adresses physiques et l'organisation de la DRAM. Cet outil a été réalisé à partir d'informations disponibles sur les sites des constructeurs, complétées par un travail de rétroconception. Les auteurs utilisent cet outil pour améliorer à la fois les attaques Rowhammer et leurs contre-mesures.

Les ECC (Error-Correcting Code, code correcteur d'erreurs) ont été considérés comme une contre-mesure possible face aux attaques Rowhammer. Afin de vérifier si ce méca-
et fournissent des méthodes permettant de tester si la fonctionnalité est présente sur un SoC donné.

Youngjoo et al. proposent une méthodologie permettant d'identifier des attaques par canal caché pour une implémentation donnée d'un algorithme [278]. L'approche développée a permis aux auteurs d'identifier un nouveau type d'attaque par canal caché exploitant les accès réalisés par le Instruction Pointer-based stride prefetcher. Cet élément de la microarchitecture des processeurs Intel va inférer les adresses des prochaines instructions afin de précharger le cache avec les instructions en question.

Les attaques par canal caché utilisant le LLC reposent généralement sur la capacité de l'attaquant à pouvoir évincer les différentes lignes d'un ensemble de ce cache. Cela nécessite pour l'attaquant de pouvoir déterminer des ensembles minimaux d'éviction. Il s'agit d'ensembles d'adresses virtuelles qui, lorsqu'on réalise des accès en lecture à chacune des adresses qui les composent, permettent d'évincer complètement un ensemble donné du cache. Calculer explicitement cet ensemble est difficile, d'autant que l'adressage du LLC utilise les adresses physiques et que l'attaquant ne dispose pas toujours des privilèges du noyau lui permettant de retrouver la correspondance entre adresses virtuelles et physiques. Song et al. proposent donc des heuristiques pour déterminer ces ensembles [279]. Ils montrent que leur approche permet de construire ces ensembles plus rapidement que prévu.

Kurth et al. ont réalisé la rétroconception du DCA (Direct Cache Access) pour les processeurs Intel [280]. Cette fonctionnalité permet aux périphériques de réaliser des accès directement dans le LLC, ce qui améliore sensiblement les performances. Toutefois, les auteurs montrent que ce mécanisme peut être utilisé pour réaliser une attaque par canaux auxiliaires utilisant un périphérique. Ils montrent notamment qu'une carte réseau peut réaliser des attaques de type PRIME+PROBE.

### 2.2.5.3 Rétroconception et modélisation de la mémoire

Des travaux de rétroconception ont également été réalisés sur l'organisation de la mémoire à différents niveaux.

Pessl et al. ont notamment réalisé un travail de rétroconception pour modéliser l'organisation de la mémoire physique sur un ordinateur disposant de plusieurs processeurs [281]. Sur ce type de configuration, l'exploitation d'un canal caché utilisant le cache n'est pas possible car la victime est souvent localisée sur un processeur différent de celui utilisé par l'attaquant. Les auteurs montrent qu'un canal auxiliaire utilisant le DRAM row buffer, qui est partagé entre les différents processeurs, est possible. Pour cela ils proposent deux techniques pour rétroconcevoir l'association d'une adresse mémoire avec la mémoire physique, afin de déterminer notamment les channel, rank et bank correspondant à une adresse.

De même, Tatar et al. ont développé RAMSES [282], un outil permettant de modéliser la correspondance entre les adresses physiques et l'organisation de la DRAM. Cet outil a été réalisé à partir d'informations disponibles sur les sites des constructeurs, complétées par un travail de rétroconception. Les auteurs utilisent cet outil pour améliorer à la fois les attaques Rowhammer et leurs contre-mesures.

Les ECC (Error-Correcting Code, code correcteur d'erreurs) ont été considérés comme une contre-mesure possible face aux attaques Rowhammer. Afin de vérifier si ce méca-
nisme est efficace, Cojocar et al. ont proposé une technique permettant de rétroconcevoir
l'algorithme utilisé dans les ECC de certaines mémoires DRAM [283]. A l'aide de ce tra-
vail, ils démontrent que des attaques Rowhammer sont toujours possibles, en dépit de
l'ECC.

Frigo et al. ont réalisé un travail de rétroconception du TRR (Target Row Refresh), un ensemble de contre-mesures contre Rowhammer implémenté dans les circuits imprimés de DRAM [284]. Ce travail leur permet d'évaluer la robustesse du mécanisme. Les auteurs démontrent que des variantes de l'attaque Rowhammer sont toujours possibles sur les circuits de DRAM, y compris sur les modèles les plus récents qui sont protégés par le TRR.

Des travaux se sont également intéressés à retrouver la correspondance entre adresses virtuelles et physiques. Cette information est utile pour un attaquant qui vise les caches adressés physiquement et qui ne dispose pas des privilèges du noyau de OS. Islam et al. ont notamment proposé d'exploiter le mécanisme de résolution des dépendances entre lectures et écritures mémoire, utilisé par le processeur pour spéculer les lectures, afin d'accélérer la rétroconception de la correspondance entre adresses physiques et virtuelles [285].

2.2.5.4 Rétroconception du microcode et du décodage du jeu d'instruc-
tion

Les processeurs x86 développés par Intel et AMD utilisent un étage de traduction des
instructions en micro-instruction. Cet étage réalise la traduction à l'aide d'un *microcode*
chargé dans une mémoire interne du processeur. Chaque processeur possède une version
originale du *microcode*, située dans une mémoire ROM, qui a été développée lors de sa
fabrication. Toutefois, il est possible de mettre à jour logiciellement ce *microcode*, lors de
l'exécution. Les processeurs comprennent un mécanisme permettant de mettre à jour la
mémoire interne utilisée pour la traduction, à partir d'une nouvelle version du *microcode*
située dans la DRAM. Cette mise à jour est éphémère et sera perdue lors de l'extinction
du processeur. Il est donc nécessaire de recommencer le processus à chaque redémarrage
de la machine.

L'intégrité du *microcode* est fondamentale pour la sécurité du processeur car certaines instructions, notamment celles permettant de gérer les enclaves SGX, sont entièrement réalisées par des programmes du *microcode*. Les mises à jour du *microcode* permettent en outre de corriger certaines erreurs des processeurs ou d'implémenter des contre-mesures.

Afin de se prémunir des attaques qui viseraient à charger un *microcode* malveillant ou défectueux, celui-ci est signé et le processeur vérifie la signature avant le chargement. En outre, sur les versions récentes des processeurs, ce *microcode* est chiffré. Son format est propriétaire et les constructeurs ne documentent pas précisément les opérations réalisées par le *microcode*.

Des chercheurs se sont intéressés à la rétroconception du *microcode*. Cette étape permet notamment d'analyser les contre-mesures proposées par les constructeurs et d'identifier de potentielles vulnérabilités voire des portes dérobées placées par les constructeurs.

Des chercheurs de l'université de Bochum se sont notamment intéressés à la rétroconcep-
tion du *microcode* des processeurs AMD [286, 287]. Leur travail s'est d'abord focalisé sur
la procédure de mise-à-jour du *microcode* puis sur la rétroconception du format. Ils
proposent également d'implémenter différents mécanismes, légitimes ou malveillants, en
nisme est efficace, Cojocar et al. ont proposé une technique permettant de rétroconcevoir
l'algorithme utilisé dans les ECC de certaines mémoires DRAM [283]. A l'aide de ce tra-
vail, ils démontrent que des attaques Rowhammer sont toujours possibles, en dépit de
l'ECC.

Frigo et al. ont réalisé un travail de rétroconception du TRR (Target Row Refresh), un ensemble de contre-mesures contre Rowhammer implémenté dans les circuits imprimés de DRAM [284]. Ce travail leur permet d'évaluer la robustesse du mécanisme. Les auteurs démontrent que des variantes de l'attaque Rowhammer sont toujours possibles sur les circuits de DRAM, y compris sur les modèles les plus récents qui sont protégés par le TRR.

Des travaux se sont également intéressés à retrouver la correspondance entre adresses virtuelles et physiques. Cette information est utile pour un attaquant qui vise les caches adressés physiquement et qui ne dispose pas des privilèges du noyau de OS. Islam et al. ont notamment proposé d'exploiter le mécanisme de résolution des dépendances entre lectures et écritures mémoire, utilisé par le processeur pour spéculer les lectures, afin d'accélérer la rétroconception de la correspondance entre adresses physiques et virtuelles [285].

2.2.5.4 Rétroconception du microcode et du décodage du jeu d'instruc-
tion

Les processeurs x86 développés par Intel et AMD utilisent un étage de traduction des
instructions en micro-instruction. Cet étage réalise la traduction à l'aide d'un microcode
chargé dans une mémoire interne du processeur. Chaque processeur possède une version
originale du microcode, située dans une mémoire ROM, qui a été développée lors de sa
fabrication. Toutefois, il est possible de mettre à jour logiciellement ce microcode, lors de
l'exécution. Les processeurs comprennent un mécanisme permettant de mettre à jour la
mémoire interne utilisée pour la traduction, à partir d'une nouvelle version du microcode
située dans la DRAM. Cette mise à jour est éphémère et sera perdue lors de l'extinction
du processeur. Il est donc nécessaire de recommencer le processus à chaque redémarrage
de la machine.

L'intégrité du *microcode* est fondamentale pour la sécurité du processeur car certaines instructions, notamment celles permettant de gérer les enclaves SGX, sont entièrement réalisées par des programmes du *microcode*. Les mises à jour du *microcode* permettent en outre de corriger certaines erreurs des processeurs ou d'implémenter des contre-mesures.

Afin de se prémunir des attaques qui viseraient à charger un *microcode* malveillant ou défectueux, celui-ci est signé et le processeur vérifie la signature avant le chargement. En outre, sur les versions récentes des processeurs, ce *microcode* est chiffré. Son format est propriétaire et les constructeurs ne documentent pas précisément les opérations réalisées par le *microcode*.

Des chercheurs se sont intéressés à la rétroconception du *microcode*. Cette étape permet notamment d'analyser les contre-mesures proposées par les constructeurs et d'identifier de potentielles vulnérabilités voire des portes dérobées placées par les constructeurs.

Des chercheurs de l'université de Bochum se sont notamment intéressés à la rétroconcep-
tion du *microcode* des processeurs AMD [286, 287]. Leur travail s'est d'abord focalisé sur
la procédure de mise-à-jour du *microcode* puis sur la rétroconception du format. Ils
proposent également d'implémenter différents mécanismes, légitimes ou malveillants, en
modifiant ce *microcode*. Toutefois, ce travail ne peut être réalisé que sur d'anciennes versions des processeurs AMD. En effet, dans les versions plus récentes des microprocesseurs, les constructeurs signent et chiffrent leur *microcode*.

Récemment, des ingénieurs de l'entreprise russe Positive Technology ont toutefois réussi à obtenir une version en clair du *microcode* des processeurs Intel Atom. Ils ont pour cela exploité des vulnérabilités dans certaines cartes mères et dans le *firmware* du CSME qui permettent de déverrouiller la protection empêchant la mise au point du processeur et du *chipset*, via le protocole USB [288]. L'exploitation de ces vulnérabilités leur permet *in fine* d'accéder à un bus interne des processeurs, d'extraire le *microcode* et même de le modifier sur le processeur [289]. Cela nécessite toutefois que le processeur soit dans un état spécifique de mise au point et de disposer d'un accès physique à l'un des ports USB de la machine. Les auteurs ont depuis initié un travail de rétroconception de ce *microcode*.

Christopher Domas s'est également intéressé à la sécurité des microprocesseurs au niveau de l'ISA afin d'identifier des instructions non documentées ou des portes dérobées [290, 291]. Toutefois, les résultats de ces travaux concernent des versions absolètes de processeurs implémentant l'architecture x86.

## 2.3 Contre-mesures logicielles face aux attaques contre la microarchitecture

Face aux différentes attaques contre la microarchitecture, qui exploitent des vulnérabilités matérielles, des contre-mesures logicielles ont été proposées. Ces contre-mesures sont essentielles quand le matériel ne peut être mis à jour. En outre, certaines contre-mesures matérielles nécessitent d'être configurées par le logiciel.

Certaines contre-mesures permettent de lutter contre plusieurs types d'attaques. Ainsi, Oliverio et al. ont proposé un mécanisme robuste de déduplication des pages qui permet de se prévenir ou de complexifier à la fois des attaques par canaux auxiliaires utilisant le cache et des attaques Rawhammer [292].

De même le projet JavaScript Zero vise à limiter les possibilités offertes par ce langage qui permettent de réaliser différentes attaques contre la microarchitecture [293]. Ces protections sont efficaces contre un large spectre de vulnérabilités mais ne concernent que leur exploitation depuis JavaScript.

Irazoqui et al. ont également développé MASCAT, un outil d'analyse statique des programmes qui visent à détecter un large spectre d'attaques contre la microarchitecure [294]. L'objectif est de fournir un outil qui pourrait être utilisé par les fournisseurs de cloud computing ou d'applications pour smartphone afin de vérifier si les applications sont malveillantes avant de les déployer ou de les publier.

Afin de lutter efficacement contre les attaques logicielles par canaux auxiliaires et celles utilisant l'exécution transitoire, il apparaît de plus en plus nécessaire d'établir un nouveau contrat entre le logiciel et le matériel. En effet, certaines contre-mesures nécessitent un support matériel. Toutefois, ces contre-mesures nécessitent un paramétrage qui doit être réalisé par le logiciel. Cela permet entre autres de limiter l'impact des contre-mesures en ne les utilisant que lorsque cela est nécessaire. En outre, ces contre-mesures nécessitent de définir des domaines d'isolation ou d'identifier des données confidentielles à protéger. En
modifiant ce *microcode*. Toutefois, ce travail ne peut être réalisé que sur d'anciennes versions des processeurs AMD. En effet, dans les versions plus récentes des microprocesseurs, les constructeurs signent et chiffrent leur *microcode*.

Récemment, des ingénieurs de l'entreprise russe Positive Technology ont toutefois réussi à obtenir une version en clair du *microcode* des processeurs Intel Atom. Ils ont pour cela exploité des vulnérabilités dans certaines cartes mères et dans le *firmware* du CSME qui permettent de déverrouiller la protection empêchant la mise au point du processeur et du *chipset*, via le protocole USB [288]. L'exploitation de ces vulnérabilités leur permet *in fine* d'accéder à un bus interne des processeurs, d'extraire le *microcode* et même de le modifier sur le processeur [289]. Cela nécessite toutefois que le processeur soit dans un état spécifique de mise au point et de disposer d'un accès physique à l'un des ports USB de la machine. Les auteurs ont depuis initié un travail de rétroconception de ce *microcode*.

Christopher Domas s'est également intéressé à la sécurité des microprocesseurs au niveau de l'ISA afin d'identifier des instructions non documentées ou des portes dérobées [290, 291]. Toutefois, les résultats de ces travaux concernent des versions absolètes de processeurs implémentant l'architecture x86.

## 2.3 Contre-mesures logicielles face aux attaques contre la microarchitecture

Face aux différentes attaques contre la microarchitecture, qui exploitent des vulnérabilités matérielles, des contre-mesures logicielles ont été proposées. Ces contre-mesures sont essentielles quand le matériel ne peut être mis à jour. En outre, certaines contre-mesures matérielles nécessitent d'être configurées par le logiciel.

Certaines contre-mesures permettent de lutter contre plusieurs types d'attaques. Ainsi, Oliverio et al. ont proposé un mécanisme robuste de déduplication des pages qui permet de se prévenir ou de complexifier à la fois des attaques par canaux auxiliaires utilisant le cache et des attaques Rawhammer [292].

De même le projet JavaScript Zero vise à limiter les possibilités offertes par ce langage qui permettent de réaliser différentes attaques contre la microarchitecture [293]. Ces protections sont efficaces contre un large spectre de vulnérabilités mais ne concernent que leur exploitation depuis JavaScript.

Irazoqui et al. ont également développé MASCAT, un outil d'analyse statique des programmes qui visent à détecter un large spectre d'attaques contre la microarchitecure [294]. L'objectif est de fournir un outil qui pourrait être utilisé par les fournisseurs de *cloud computing* ou d'applications pour *smartphone* afin de vérifier si les applications sont malveillantes avant de les déployer ou de les publier.

Afin de lutter efficacement contre les attaques logicielles par canaux auxiliaires et celles utilisant l'exécution transitoire, il apparaît de plus en plus nécessaire d'établir un nouveau contrat entre le logiciel et le matériel. En effet, certaines contre-mesures nécessitent un support matériel. Toutefois, ces contre-mesures nécessitent un paramétrage qui doit être réalisé par le logiciel. Cela permet entre autres de limiter l'impact des contre-mesures en ne les utilisant que lorsque cela est nécessaire. En outre, ces contre-mesures nécessitent de définir des domaines d'isolation ou d'identifier des données confidentielles à protéger. En
général, ces éléments dépendent du contexte et ne peuvent être spécifiés que par le code
de l'application ou celui de l'OS.

Ge et al. ont notamment milité pour l'établissement d'un tel contrat afin que l'OS puisse
assurer une isolation temporelle [295, 296]. Plus récemment, Guarnieri et al. ont pro-
posé une approche reposant sur un tel contrat pour lutter contre l'exécution spécula-
tive [297].

La plupart des contre-mesures logicielles sont spécifiques à une classe d'attaques. Par la
suite, nous détaillons les contre-mesures logicielles qui ont été proposées pour lutter contre
les attaques logicielles par canaux auxiliaires (section 2.3.1). Nous évoquons ensuite en
section 2.3.2 les contre-mesures qui visent plus spécifiquement les attaques exploitant
l'exécution transitoire dont l'exploitation d'un canal auxiliaire n'est qu'une étape. En-
fin nous présentons les protections logicielles permettant de lutter contre les attaques
Rawhammer 2.3.3.

## 2.3.1 Contre-mesures logicielles face aux attaques par canaux auxiliaires

Des travaux se sont intéressés à dresser un état de l'art des protections contre les at-
taques par canaux auxiliaires temporels [298] et plus spécifiquement celles utilisant le
cache [299].

Par la suite nous détaillons différents types de contre-mesures logicielles :

- l'analyse statique et dynamique des programmes afin d'identifier les programmes vulnérables à ces attaques ou de les protéger (section 2.3.1.1);

- les contre-mesures liées à la gestion du cache (section 2.3.1.2);

- les contre-mesures au niveau de l'OS (section 2.3.1.3);

- la détection des attaques par canaux auxiliaires (section 2.3.1.4).

### 2.3.1.1 Identification et protection des programmes vulnérables

Les attaques par canaux auxiliaires reposent généralement sur la présence de vulnérabi-
lités dans le code des programmes (applications, OS, etc.) qui réalisent des opérations
(notamment des accès mémoire) qui dépendent de données secrètes. Des approches ont
été proposées afin d'identifier ces vulnérabilités par analyse statique ou dynamique ou de
protéger le code des applications contre ces vulnérabilités.

Une des approches permettant d'éviter ces vulnérabilités consiste à développer des appli-
cations *constant-time*, c'est à dire dont le temps d'exécution ne doit pas varier en fonction
des valeurs des secrets. Cela implique que les accès mémoire qui utilisent le cache par-
tagé ne doivent pas dépendre des valeurs secrètes. Cette approche doit être appliquée aux
programmes critiques pour la sécurité, notamment ceux réalisant des opérations crypto-
graphiques, mais elle est difficile à généraliser à tous les programmes. En outre, ces ap-
proches dépendent de la configuration de la microarchitecture car, par exemple, les temps
d'exécution des instructions peuvent varier d'une microarchitecture à une autre.

**Analyses statiques** Différentes approches d'analyse statique ont été proposées pour lutter contre les attaques par canaux auxiliaires. Ainsi, Doychev et al. ont proposé CacheAudit [300], un outil d'analyse statique qui permet de vérifier si des programmes sont
général, ces éléments dépendent du contexte et ne peuvent être spécifiés que par le code
de l'application ou celui de l'OS.

Ge et al. ont notamment milité pour l'établissement d'un tel contrat afin que l'OS puisse
assurer une isolation temporelle [295, 296]. Plus récemment, Guarnieri et al. ont pro-
posé une approche reposant sur un tel contrat pour lutter contre l'exécution spécula-
tive [297].

La plupart des contre-mesures logicielles sont spécifiques à une classe d'attaques. Par la
suite, nous détaillons les contre-mesures logicielles qui ont été proposées pour lutter contre
les attaques logicielles par canaux auxiliaires (section 2.3.1). Nous évoquons ensuite en
section 2.3.2 les contre-mesures qui visent plus spécifiquement les attaques exploitant
l'exécution transitoire dont l'exploitation d'un canal auxiliaire n'est qu'une étape. En-
fin nous présentons les protections logicielles permettant de lutter contre les attaques
Rawhammer 2.3.3.

## 2.3.1 Contre-mesures logicielles face aux attaques par canaux auxiliaires

Des travaux se sont intéressés à dresser un état de l'art des protections contre les at-
taques par canaux auxiliaires temporels [298] et plus spécifiquement celles utilisant le
cache [299].

Par la suite nous détaillons différents types de contre-mesures logicielles :

- l'analyse statique et dynamique des programmes afin d'identifier les programmes vulnérables à ces attaques ou de les protéger (section 2.3.1.1);

- les contre-mesures liées à la gestion du cache (section 2.3.1.2);

- les contre-mesures au niveau de l'OS (section 2.3.1.3);

- la détection des attaques par canaux auxiliaires (section 2.3.1.4).

### 2.3.1.1 Identification et protection des programmes vulnérables

Les attaques par canaux auxiliaires reposent généralement sur la présence de vulnérabi-
lités dans le code des programmes (applications, OS, etc.) qui réalisent des opérations
(notamment des accès mémoire) qui dépendent de données secrètes. Des approches ont
été proposées afin d'identifier ces vulnérabilités par analyse statique ou dynamique ou de
protéger le code des applications contre ces vulnérabilités.

Une des approches permettant d'éviter ces vulnérabilités consiste à développer des appli-
cations *constant-time*, c'est à dire dont le temps d'exécution ne doit pas varier en fonction
des valeurs des secrets. Cela implique que les accès mémoire qui utilisent le cache par-
tagé ne doivent pas dépendre des valeurs secrètes. Cette approche doit être appliquée aux
programmes critiques pour la sécurité, notamment ceux réalisant des opérations crypto-
graphiques, mais elle est difficile à généraliser à tous les programmes. En outre, ces ap-
proches dépendent de la configuration de la microarchitecture car, par exemple, les temps
d'exécution des instructions peuvent varier d'une microarchitecture à une autre.

**Analyses statiques** Différentes approches d'analyse statique ont été proposées pour lutter contre les attaques par canaux auxiliaires. Ainsi, Doychev et al. ont proposé CacheAudit [300], un outil d'analyse statique qui permet de vérifier si des programmes sont
vulnérables à des attaques par canaux auxiliaires utilisant le cache. Le programme analyse le code binaire des applications et repose sur une description de la configuration des caches. Il réalise une surapproximation des canaux possibles afin de s'assurer qu'aucune fuite n'est possible. Il peut en revanche refuser des programmes qui ne sont pas, en pratique, vulnérables à ces attaques.

Barthe et al. ont formalisé une propriété de non-interférence qui permet de capturer les canaux auxiliaires utilisant le cache [301]. Cette propriété garantit l'absence de fuite d'information pour des programmes qui appliquent une approche *constant-time* et utilisent une mémoire dédiée pour manipuler des secrets. Les auteurs proposent également une analyse statique permettant de garantir cette propriété. Ils apportent la preuve de la correction de l'analyse à l'aide de l'assistant à la preuve Coq.

L'outil Valgrind d'analyse du code binaire des applications dispose d'un module permettant de vérifier que le code d'une fonction est *constant-time* [302]. Almeida et al. ont également proposé une approche permettant de vérifier automatiquement la propriété de *constant-time* au niveau du compilateur LLVM [303].

**Analyses dynamiques** Des approches dynamiques ont également été proposées afin d'analyser dynamiquement les applications et d'identifier des vulnérabilités aux attaques par canaux auxiliaires. Ainsi Wang et al. ont proposé un outil permettant d'identifier de potentielles vulnérabilités à l'aide d'une analyse des traces de l'application, d'une exécution symbolique et d'un modèle du cache [304].

Xiao et al. proposent une analyse différentielle qui permet dynamiquement d'identifier de potentielles vulnérabilités dans les implémentations TLS exécutées dans l'enclave SGX [305]. Toutefois l'approche se concentre sur les fuites liées au flot de contrôle. Weiser et al. adoptent une approche similaire qui prend également en compte les fuites liées au données [306].

Wichelmann et al. utilisent l'instrumentation dynamique de binaires et une analyse de l'information mutuelle pour identifier des vulnérabilités dans le code binaire d'implémentations propriétaires [307].

Wang et al. proposent une analyse des traces, obtenues avec le mécanisme Intel PT, afin d'identifier des canaux auxiliaires qui sont liés aux variations temporelles entre deux accès mémoire, à l'aide d'une analyse de graphes [308].

**Diversification** Des approches de diversification, qui visent à faire varier aléatoirement les accès mémoire et le flot d'exécution d'un programme à chaque exécution, ont également été proposées. Ces approches visent à générer du bruit, afin de masquer les différences measurable dans l'exécution d'un programme qui sont liées à des fuites d'information. Ainsi, Crane et al. proposent de générer différentes variantes des fonctions d'un programme, appelées fragments, puis de compiler l'application de manière à ce qu'elle choisisse aléatoirement le fragment à exécuter pour chaque exécution du programme [309].

De même, Rane et al. proposent une technique d'obfuscation au niveau du code source du programme, afin de donner l'illusion que différents chemins d'exécution ont été empruntés [310].

Brasser et al. proposent une technique de déplacement aléatoire des données lors de
vulnérables à des attaques par canaux auxiliaires utilisant le cache. Le programme analyse le code binaire des applications et repose sur une description de la configuration des caches. Il réalise une surapproximation des canaux possibles afin de s'assurer qu'aucune fuite n'est possible. Il peut en revanche refuser des programmes qui ne sont pas, en pratique, vulnérables à ces attaques.

Barthe et al. ont formalisé une propriété de non-interférence qui permet de capturer les canaux auxiliaires utilisant le cache [301]. Cette propriété garantit l'absence de fuite d'information pour des programmes qui appliquent une approche *constant-time* et utilisent une mémoire dédiée pour manipuler des secrets. Les auteurs proposent également une analyse statique permettant de garantir cette propriété. Ils apportent la preuve de la correction de l'analyse à l'aide de l'assistant à la preuve Coq.

L'outil Valgrind d'analyse du code binaire des applications dispose d'un module permettant de vérifier que le code d'une fonction est *constant-time* [302]. Almeida et al. ont également proposé une approche permettant de vérifier automatiquement la propriété de *constant-time* au niveau du compilateur LLVM [303].

**Analyses dynamiques** Des approches dynamiques ont également été proposées afin d'analyser dynamiquement les applications et d'identifier des vulnérabilités aux attaques par canaux auxiliaires. Ainsi Wang et al. ont proposé un outil permettant d'identifier de potentielles vulnérabilités à l'aide d'une analyse des traces de l'application, d'une exécution symbolique et d'un modèle du cache [304].

Xiao et al. proposent une analyse différentielle qui permet dynamiquement d'identifier de potentielles vulnérabilités dans les implémentations TLS exécutées dans l'enclave SGX [305]. Toutefois l'approche se concentre sur les fuites liées au flot de contrôle. Weiser et al. adoptent une approche similaire qui prend également en compte les fuites liées au données [306].

Wichelmann et al. utilisent l'instrumentation dynamique de binaires et une analyse de l'information mutuelle pour identifier des vulnérabilités dans le code binaire d'implémentations propriétaires [307].

Wang et al. proposent une analyse des traces, obtenues avec le mécanisme Intel PT, afin d'identifier des canaux auxiliaires qui sont liés aux variations temporelles entre deux accès mémoire, à l'aide d'une analyse de graphes [308].

**Diversification** Des approches de diversification, qui visent à faire varier aléatoirement les accès mémoire et le flot d'exécution d'un programme à chaque exécution, ont également été proposées. Ces approches visent à générer du bruit, afin de masquer les différences measurable dans l'exécution d'un programme qui sont liées à des fuites d'information. Ainsi, Crane et al. proposent de générer différentes variantes des fonctions d'un programme, appelées fragments, puis de compiler l'application de manière à ce qu'elle choisisse aléatoirement le fragment à exécuter pour chaque exécution du programme [309].

De même, Rane et al. proposent une technique d'obfuscation au niveau du code source du programme, afin de donner l'illusion que différents chemins d'exécution ont été empruntés [310].

Brasser et al. proposent une technique de déplacement aléatoire des données lors de
l'exécution, afin que l'attaquant ne puisse inférer les données en fonction des accès mémoire [311]. Ils implémentent automatiquement leur approche au niveau du compilateur afin de protéger le code des applications exécutées en enclaves SGX.

### 2.3.1.2 Gestion du cache

Les différents caches sont utilisés par de nombreuses attaques par canaux auxiliaires. Même si d'autres canaux existent, ils constituent une source de vulnérabilités importante. Des approches ont donc été proposées pour empêcher ou limiter les canaux auxiliaires utilisant le cache.

Une première approche consiste à verrouiller ou partitionner le cache. Ainsi, STEALTH-MEM [312] propose un système, implémenté au niveau de l'OS, qui permet de verrouiller certaines lignes de caches, qui ne sont jamais évincées. Ces lignes peuvent être utilisées par les applications pour y stocker des données confidentielles.

Zhou et al. s'intéressent à la protection du partage de pages physiques entre différentes machines virtuelles [313]. Ce partage est utilisé par de nombreuses attaques par canaux auxiliaires qui visent le LLC, notamment FLUSH+RELOAD. Afin de permettre ce partage, les auteurs implémentent un mécanisme de sécurité au niveau de l'OS afin de s'assurer que ces pages ne partagent pas les mêmes lignes du LLC.

Des approches ont également proposé d'utiliser la technologie Intel CAT [314] qui permet de partitionner le LLC. Il s'agit d'une fonctionnalité matérielle mais qui doit être configurée par le logiciel. Cette technologie a été introduite pour limiter la latence des applications qui le nécessitent. Liu et al. ont cependant démontré qu'elle pouvait également être utilisée pour protéger les applications des attaques par canaux auxiliaires [315].

CAT est un mécanisme qui a l'avantage d'être disponible sur les processeurs x86 existants. Toutefois, il ne fournit pas un partitionnement strict du cache. Kiriansky et al. ont proposé DAWG, une approche qui implémente un partitionnement robuste du cache mais nécessite quelques modifications au niveau matériel [316]. Un support au niveau de l'OS est également nécessaire pour isoler les processus dans différents domaines.

Les approches de partitionnement du cache ont un impact sur les performances puisque la taille du cache disponible pour une application est réduite. Les approches précédentes impactent l'intégralité du code des applications. Dessouky et al. proposent une approche à grain fin permettant de partitionner dynamiquement le cache, seulement lorsque des composants logiciels critiques, qui manipulent par exemple des clés cryptographiques, sont exécutés [317]. Cela permet, le reste du temps, d'éviter d'impacter les applications qui ne contiennent pas de données confidentielles. Leur approche nécessite des modifications matérielles et un support au niveau de l'OS.

Une autre approche consiste à introduire de l'aléa dans la fonction permettant d'associer une adresse physique à un ensemble de lignes du cache. Cette contre-mesure permet de lutter contre les attaques qui doivent réaliser l'éviction d'un ensemble de lignes du LLC (notamment EVICT+RELOAD et PRIME+PROBE). Toutefois ces contre-mesures nécessitent des modifications importantes au niveau matériel ou des changements fréquents de clés. Werner et al. ont proposé une approche qui repose sur une clé et un identifiant du domaine de sécurité [318]. Cette approche nécessite toutefois des modifications matérielles et un support logiciel pour associer les domaines de sécurité aux composants logiciels.
l'exécution, afin que l'attaquant ne puisse inférer les données en fonction des accès mémoire [311]. Ils implémentent automatiquement leur approche au niveau du compilateur afin de protéger le code des applications exécutées en enclaves SGX.

### 2.3.1.2 Gestion du cache

Les différents caches sont utilisés par de nombreuses attaques par canaux auxiliaires. Même si d'autres canaux existent, ils constituent une source de vulnérabilités importante. Des approches ont donc été proposées pour empêcher ou limiter les canaux auxiliaires utilisant le cache.

Une première approche consiste à verrouiller ou partitionner le cache. Ainsi, STEALTH-MEM [312] propose un système, implémenté au niveau de l'OS, qui permet de verrouiller certaines lignes de caches, qui ne sont jamais évincées. Ces lignes peuvent être utilisées par les applications pour y stocker des données confidentielles.

Zhou et al. s'intéressent à la protection du partage de pages physiques entre différentes machines virtuelles [313]. Ce partage est utilisé par de nombreuses attaques par canaux auxiliaires qui visent le LLC, notamment FLUSH+RELOAD. Afin de permettre ce partage, les auteurs implémentent un mécanisme de sécurité au niveau de l'OS afin de s'assurer que ces pages ne partagent pas les mêmes lignes du LLC.

Des approches ont également proposé d'utiliser la technologie Intel CAT [314] qui permet de partitionner le LLC. Il s'agit d'une fonctionnalité matérielle mais qui doit être configurée par le logiciel. Cette technologie a été introduite pour limiter la latence des applications qui le nécessitent. Liu et al. ont cependant démontré qu'elle pouvait également être utilisée pour protéger les applications des attaques par canaux auxiliaires [315].

CAT est un mécanisme qui a l'avantage d'être disponible sur les processeurs x86 existants. Toutefois, il ne fournit pas un partitionnement strict du cache. Kiriansky et al. ont proposé DAWG, une approche qui implémente un partitionnement robuste du cache mais nécessite quelques modifications au niveau matériel [316]. Un support au niveau de l'OS est également nécessaire pour isoler les processus dans différents domaines.

Les approches de partitionnement du cache ont un impact sur les performances puisque la taille du cache disponible pour une application est réduite. Les approches précédentes impactent l'intégralité du code des applications. Dessouky et al. proposent une approche à grain fin permettant de partitionner dynamiquement le cache, seulement lorsque des composants logiciels critiques, qui manipulent par exemple des clés cryptographiques, sont exécutés [317]. Cela permet, le reste du temps, d'éviter d'impacter les applications qui ne contiennent pas de données confidentielles. Leur approche nécessite des modifications matérielles et un support au niveau de l'OS.

Une autre approche consiste à introduire de l'aléa dans la fonction permettant d'associer une adresse physique à un ensemble de lignes du cache. Cette contre-mesure permet de lutter contre les attaques qui doivent réaliser l'éviction d'un ensemble de lignes du LLC (notamment EVICT+RELOAD et PRIME+PROBE). Toutefois ces contre-mesures nécessitent des modifications importantes au niveau matériel ou des changements fréquents de clés. Werner et al. ont proposé une approche qui repose sur une clé et un identifiant du domaine de sécurité [318]. Cette approche nécessite toutefois des modifications matérielles et un support logiciel pour associer les domaines de sécurité aux composants logiciels.
L'utilisation de la mémoire transactionnelle, notamment fournie par Intel TSX, permet également, par effet de bord, de contrer les attaques par canaux auxiliaires utilisant le cache [319].

### 2.3.1.3 Contre-mesures au niveau de l'OS

Certaines attaques par canal auxiliaire visent plus particulièrement l'OS ou un des services qu'il fournit. Des contre-mesures logicielles ont donc été proposées au niveau du noyau de l'OS.

#### Protection de l'ASLR
Certaines attaques par canaux auxiliaires, présentées en section 2.2.1.1, visent à casser l'ASLR mise en place au niveau du noyau de l'OS [208-210]. Ce type d'attaques permet ensuite de réaliser facilement des attaque de type ROP exploitant des vulnérabilités du noyau.

Des contre-mesures ont été proposées pour lutter contre ces attaques, notamment KAI-SER [320] et LAZARUS [321]. KAISER supprime les pages du noyau de l'espace virtuel des applications. Les auteurs ont proposé une modification du noyau Linux implémentant cette approche. Cette modification a également permis de lutter efficacement contre les attaques Meltdown, pour les processeurs qui sont vulnérables à cette attaque. Elle a été adoptée par l'équipe de développement du noyau Linux dans sa solution KPIT [322].

KPTI est toutefois désactivée par défaut pour les processeurs qui ne sont pas vulnérables, en raison de son impact sur les performances. Cependant, Canella et al. ont démontré que les contre-mesures matérielles des derniers processeurs Intel permettaient tout de même de casser l'ASLR [323]. Les auteurs ont proposé une nouvelle contre-mesure logicielle plus robuste afin de lutter contre ce type d'attaques.

#### Génération de bruit
Zhang et al. proposent que l'OS nettoie régulièrement les caches L1 et L2 afin d'ajouter du bruit, ce qui limite l'efficacité des attaques PRIME+PROBE [324]. Leur objectif est de fournir un moyen d'autodéfense pour les machines virtuelles déployées dans le cloud, sans nécessiter d'effort spécifique pour le développement des applications.

Varadarajan et al. combinent le nettoyage du cache L1 avec des contraintes sur l'ordonnancement qui imposent une durée minimale d'exécution d'une machine virtuelle [325].

HYPERRACE [326] vise à protéger les enclaves SGX contre les attaques par canal caché de type *port contention*. Ces attaques doivent être conduites par un programme s'exécutant simultanément sur le même cœur que l'enclave. Cela est possible en raison de l'*hyperthreading*. Les auteurs proposent d'exécuter un fil d'exécution maîtrisé sur le même cœur physique que l'enclave et de s'assurer que ce fil d'exécution est bien colocalisé avec le code de l'enclave. La solution proposée évite de désactiver l'*hyperthreading* de manière globale, ce qui impacte les performances de toutes les applications. Cette contre-mesure nécessite le support de l'OS pour ordonnancer les fils d'exécution mais ne suppose pas que l'OS est de confiance, grâce au test de colocalisation.

### 2.3.1.4 Détection des attaques contre le cache

Les attaques par canaux auxiliaires qui utilisent le cache génèrent un comportement d'accès au cache anormal, notamment ence qui concerne le ratio entre les *cache hit* et les *cache
L'utilisation de la mémoire transactionnelle, notamment fournie par Intel TSX, permet également, par effet de bord, de contrer les attaques par canaux auxiliaires utilisant le cache [319].

### 2.3.1.3 Contre-mesures au niveau de l'OS

Certaines attaques par canal auxiliaire visent plus particulièrement l'OS ou un des services qu'il fournit. Des contre-mesures logicielles ont donc été proposées au niveau du noyau de l'OS.

#### Protection de l'ASLR
Certaines attaques par canaux auxiliaires, présentées en section 2.2.1.1, visent à casser l'ASLR mise en place au niveau du noyau de l'OS [208-210]. Ce type d'attaques permet ensuite de réaliser facilement des attaque de type ROP exploitant des vulnérabilités du noyau.

Des contre-mesures ont été proposées pour lutter contre ces attaques, notamment KAI-SER [320] et LAZARUS [321]. KAISER supprime les pages du noyau de l'espace virtuel des applications. Les auteurs ont proposé une modification du noyau Linux implémentant cette approche. Cette modification a également permis de lutter efficacement contre les attaques Meltdown, pour les processeurs qui sont vulnérables à cette attaque. Elle a été adoptée par l'équipe de développement du noyau Linux dans sa solution KPIT [322].

KPTI est toutefois désactivée par défaut pour les processeurs qui ne sont pas vulnérables, en raison de son impact sur les performances. Cependant, Canella et al. ont démontré que les contre-mesures matérielles des derniers processeurs Intel permettaient tout de même de casser l'ASLR [323]. Les auteurs ont proposé une nouvelle contre-mesure logicielle plus robuste afin de lutter contre ce type d'attaques.

#### Génération de bruit
Zhang et al. proposent que l'OS nettoie régulièrement les caches L1 et L2 afin d'ajouter du bruit, ce qui limite l'efficacité des attaques PRIME+PROBE [324]. Leur objectif est de fournir un moyen d'autodéfense pour les machines virtuelles déployées dans le cloud, sans nécessiter d'effort spécifique pour le développement des applications.

Varadarajan et al. combinent le nettoyage du cache L1 avec des contraintes sur l'ordonnancement qui imposent une durée minimale d'exécution d'une machine virtuelle [325].

HYPERRACE [326] vise à protéger les enclaves SGX contre les attaques par canal caché de type *port contention*. Ces attaques doivent être conduites par un programme s'exécutant simultanément sur le même cœur que l'enclave. Cela est possible en raison de l'*hyperthreading*. Les auteurs proposent d'exécuter un fil d'exécution maîtrisé sur le même cœur physique que l'enclave et de s'assurer que ce fil d'exécution est bien colocalisé avec le code de l'enclave. La solution proposée évite de désactiver l'*hyperthreading* de manière globale, ce qui impacte les performances de toutes les applications. Cette contre-mesure nécessite le support de l'OS pour ordonnancer les fils d'exécution mais ne suppose pas que l'OS est de confiance, grâce au test de colocalisation.

### 2.3.1.4 Détection des attaques contre le cache

Les attaques par canaux auxiliaires qui utilisent le cache génèrent un comportement d'accès au cache anormal, notamment ence qui concerne le ratio entre les *cache hit* et les *cache
miss. Des approches ont proposé de détecter ces comportements.

CloudRadar [327] combine une détection par signature, qui permet d'identifier l'exécution d'une machine virtuelle exécutant une application à protéger (typiquement, une application réalisant des opérations cryptographiques) et une détection d'anomalies afin d'identifier des attaques potentielles. L'approche utilise les compteurs de performances pour réaliser la détection. La corrélation entre les deux types de détection permet d'identifier des attaques par canaux auxiliaires contre l'application.

CacheShield [328] propose une approche similaire mais ne nécessite que de surveiller l'application cible. De même Mushtaq et al. évaluent les capacités de détection d'une telle approche dans des conditions proches de celles rencontrées dans un environnement de type cloud, en présence de différentes applications et d'une charge système réaliste [329].

## 2.3.2 Protections contre les attaques exploitant l'exécution transitoire

Les attaques exploitant l'exécution transitoire sont à distinguer des attaques par canaux auxiliaires. En effet, l'utilisation d'un canal auxiliaire ne représente que la dernière étape de ce type d'attaque. En outre, ce canal est mis en place directement par le code de l'attaque (dans le cadre de Meltdown) ou par du code contrôlé par l'attaquant (dans le cadre de Spectre). Cette dernière étape correspond donc plus à un canal caché.

De ce fait, certaines contre-mesures contre les canaux auxiliaires ne permettent pas de lutter contre les attaques exploitant l'exécution transitoire. Ainsi, la programmation constant-time ne concerne que le code légitime de l'application et ne permet pas, en l'état, de lutter contre les attaques de type Spectre ou Meltdown.

Canella et al. dressent un état de l'art de ces différentes attaques et des contre-mesures qui ont été proposées pour s'en prémunir [217].

Guanciale et al. établissent un modèle formel de la microarchitecture permettant de présenter différentes formes d'exécution spéculative et out-of-order pour un processeur monocœur [330]. Ce modèle permet d'identifier de nouvelles vulnérabilités et de raisonner formellement sur le niveau de protection des contre-mesures.

### 2.3.2.1 Identification des codes vulnérables

Les attaques de type Spectre reposent sur la présence, dans le code de l'application victime, de suites d'instructions, les gadgets, que l'attaquant va chercher à faire exécuter de manière spéculative.

Des travaux se sont donc intéressés à identifier la présence de ces gadgets dans le code des applications afin d'évaluer leur état de vulnérabilité.

Ainsi, Wang et al. utilisent le moteur d'exécution symbolique KLEE qui, avec un modèle du cache et de l'exécution spéculative, leur permet d'identifier dans un programme donné, des fuites liées à l'exécution spéculative [331].

Oleksenko et al. utilisent une approche de fuzzing afin de tester une application et d'identifier les variantes V1 de Spectre (Spectre-PHT) [332].
miss. Des approches ont proposé de détecter ces comportements.

CloudRadar [327] combine une détection par signature, qui permet d'identifier l'exécution d'une machine virtuelle exécutant une application à protéger (typiquement, une application réalisant des opérations cryptographiques) et une détection d'anomalies afin d'identifier des attaques potentielles. L'approche utilise les compteurs de performances pour réaliser la détection. La corrélation entre les deux types de détection permet d'identifier des attaques par canaux auxiliaires contre l'application.

CacheShield [328] propose une approche similaire mais ne nécessite que de surveiller l'application cible. De même Mushtaq et al. évaluent les capacités de détection d'une telle approche dans des conditions proches de celles rencontrées dans un environnement de type cloud, en présence de différentes applications et d'une charge système réaliste [329].

## 2.3.2 Protections contre les attaques exploitant l'exécution transitoire

Les attaques exploitant l'exécution transitoire sont à distinguer des attaques par canaux auxiliaires. En effet, l'utilisation d'un canal auxiliaire ne représente que la dernière étape de ce type d'attaque. En outre, ce canal est mis en place directement par le code de l'attaque (dans le cadre de Meltdown) ou par du code contrôlé par l'attaquant (dans le cadre de Spectre). Cette dernière étape correspond donc plus à un canal caché.

De ce fait, certaines contre-mesures contre les canaux auxiliaires ne permettent pas de lutter contre les attaques exploitant l'exécution transitoire. Ainsi, la programmation constant-time ne concerne que le code légitime de l'application et ne permet pas, en l'état, de lutter contre les attaques de type Spectre ou Meltdown.

Canella et al. dressent un état de l'art de ces différentes attaques et des contre-mesures qui ont été proposées pour s'en prémunir [217].

Guanciale et al. établissent un modèle formel de la microarchitecture permettant de présenter différentes formes d'exécution spéculative et out-of-order pour un processeur monocœur [330]. Ce modèle permet d'identifier de nouvelles vulnérabilités et de raisonner formellement sur le niveau de protection des contre-mesures.

### 2.3.2.1 Identification des codes vulnérables

Les attaques de type Spectre reposent sur la présence, dans le code de l'application victime, de suites d'instructions, les gadgets, que l'attaquant va chercher à faire exécuter de manière spéculative.

Des travaux se sont donc intéressés à identifier la présence de ces gadgets dans le code des applications afin d'évaluer leur état de vulnérabilité.

Ainsi, Wang et al. utilisent le moteur d'exécution symbolique KLEE qui, avec un modèle du cache et de l'exécution spéculative, leur permet d'identifier dans un programme donné, des fuites liées à l'exécution spéculative [331].

Oleksenko et al. utilisent une approche de fuzzing afin de tester une application et d'identifier les variantes V1 de Spectre (Spectre-PHT) [332].
Speculator [333] est un outil qui permet d'étudier le comportement spéculatif d'une suite d'instructions à l'aide des compteurs de performance. Il s'agit d'un outil d'analyse dynamique qui ne permet pas d'identifier directement les vulnérabilités dans le code d'une application mais plutôt d'étudier précisément le comportement spéculatif afin d'identifier de nouvelles attaques ou d'étudier l'efficacité des contre-mesures.

### 2.3.2.2 Prévention des attaques de type Spectre

Différentes approches ont été proposées afin de se protéger des attaques de type Spectre. A la différence des attaques de type Meltdown, les attaques de type Spectre peuvent difficilement être résolues par une approche purement matérielle, sans modifications profondes de la microarchitecture qui impacteraient fortement les performances.

Ainsi, Intel [334], ARM [335] et AMD [336] ont publié des recommandations à l'attention des développeurs afin de lutter contre ces attaques, suivant les possibilités offertes par leurs architectures respectives et leur niveau de vulnérabilité.

L'équipe de développement du noyau Linux a notamment mis en place certaines de ces contre-mesures, qu'il est possible d'activer ou de désactiver [337]

Ces approches peuvent être classées selon trois catégories, qui correspondent aux différentes étapes de l'attaque :

- supprimer ou limiter la spéculation;

- empêcher le code spéculé à accéder à des données sensibles;

- supprimer ou limiter le canal caché;

**Suppression ou contrôle de la spéculation** La spéculation est la cause première des attaques de type Spectre. Une approche naïve pour les contrer serait de supprimer la spéculation. Cette approche ne peut malheureusement être retenue que pour des microarchitectures simples, pour des cas d'usage qui ne nécessitent pas de performances importantes.

Afin de limiter l'impact de cette contre-mesure, les constructeurs recommandent de la supprimer localement aux endroits du code potentiellement dangereux. Ce contrôle de la spéculation peut être effectué à l'aide d'instructions de sérialisation comme **LFENCE** pour les architectures x86 ou **CSDB** pour les architectures ARM qui le supportent.

Toutefois ces instruction ne bloquent pas l'exécution spéculative de toutes les instructions mais seulement de celles qui réalisent des lectures en mémoire. Elles sont donc seulement efficaces contre les attaques qui utilisent le cache comme canal caché. En outre, il s'agit d'une protection locale. Elle n'est donc pas efficace pour lutter contre Spectre-BTB, pour laquelle l'attaquant peut sauter à n'importe quel endroit de la mémoire. Elle est surtout utile pour se protéger de la variante 1 (Spectre-PHT).

En outre, cette solution impacte sensiblement les performances. Des approches ont donc été proposées pour identifier précisément les branchements qui sont susceptibles d'être vulnérables afin de ne pas déployer cette solution pour tous les branchements.

Microsoft adopte une approche par liste noire. Le compilateur place des protections uniquement lorsqu'il détecte des motifs de code qui pourraient permettre l'exécution d'une attaque [338]. oo7 [339] suit une approche similaire mais permet d'analyser le code binaire des applications.
Speculator [333] est un outil qui permet d'étudier le comportement spéculatif d'une suite d'instructions à l'aide des compteurs de performance. Il s'agit d'un outil d'analyse dynamique qui ne permet pas d'identifier directement les vulnérabilités dans le code d'une application mais plutôt d'étudier précisément le comportement spéculatif afin d'identifier de nouvelles attaques ou d'étudier l'efficacité des contre-mesures.

### 2.3.2.2 Prévention des attaques de type Spectre

Différentes approches ont été proposées afin de se protéger des attaques de type Spectre. A la différence des attaques de type Meltdown, les attaques de type Spectre peuvent difficilement être résolues par une approche purement matérielle, sans modifications profondes de la microarchitecture qui impacteraient fortement les performances.

Ainsi, Intel [334], ARM [335] et AMD [336] ont publié des recommandations à l'attention des développeurs afin de lutter contre ces attaques, suivant les possibilités offertes par leurs architectures respectives et leur niveau de vulnérabilité.

L'équipe de développement du noyau Linux a notamment mis en place certaines de ces contre-mesures, qu'il est possible d'activer ou de désactiver [337]

Ces approches peuvent être classées selon trois catégories, qui correspondent aux différentes étapes de l'attaque :

- supprimer ou limiter la spéculation;

- empêcher le code spéculé à accéder à des données sensibles;

- supprimer ou limiter le canal caché;

**Suppression ou contrôle de la spéculation** La spéculation est la cause première des attaques de type Spectre. Une approche naïve pour les contrer serait de supprimer la spéculation. Cette approche ne peut malheureusement être retenue que pour des microarchitectures simples, pour des cas d'usage qui ne nécessitent pas de performances importantes.

Afin de limiter l'impact de cette contre-mesure, les constructeurs recommandent de la supprimer localement aux endroits du code potentiellement dangereux. Ce contrôle de la spéculation peut être effectué à l'aide d'instructions de sérialisation comme **LFENCE** pour les architectures x86 ou **CSDB** pour les architectures ARM qui le supportent.

Toutefois ces instruction ne bloquent pas l'exécution spéculative de toutes les instructions mais seulement de celles qui réalisent des lectures en mémoire. Elles sont donc seulement efficaces contre les attaques qui utilisent le cache comme canal caché. En outre, il s'agit d'une protection locale. Elle n'est donc pas efficace pour lutter contre Spectre-BTB, pour laquelle l'attaquant peut sauter à n'importe quel endroit de la mémoire. Elle est surtout utile pour se protéger de la variante 1 (Spectre-PHT).

En outre, cette solution impacte sensiblement les performances. Des approches ont donc été proposées pour identifier précisément les branchements qui sont susceptibles d'être vulnérables afin de ne pas déployer cette solution pour tous les branchements.

Microsoft adopte une approche par liste noire. Le compilateur place des protections uniquement lorsqu'il détecte des motifs de code qui pourraient permettre l'exécution d'une attaque [338]. oo7 [339] suit une approche similaire mais permet d'analyser le code binaire des applications.
Ces approches permettent de limiter l'impact sur les performance mais elles ne sont pas robustes car d'autres motifs de code peuvent permettre de réaliser l'attaque.

Guarnieri *et al.* adoptent une approche conservatrice [340]. Ils analysent statiquement le code de l'application et essaient de prouver que l'exécution spéculative respecte une propriété de non-interférence. Dans le cas contraire, le branchement doit être protégé. L'analyse réalise une surapproximation, ce qui peut conduire à protéger plus de branchements que nécessaire. En revanche, les branchements vulnérables sont systématiquement protégés.

Afin de lutter contre les autres variantes de Spectre, des techniques ont également été proposées afin d'empêcher l'empoisonnement des *buffer* utilisés par le processeur pour la spéculation.

Ainsi, Google a proposé Retpoline [341], une solution purement logicielle contre les attaques Spectre-BTB. Elle consiste à remplacer, dans le code des applications, les branchements indirects par des retours de fonction, en ayant pris soin de pousser l'adresse du saut sur la pile. Le comportement spéculatif sur les retours de fonction étant contrôlé par le *Return Stack Buffer*, l'attaquant ne peut plus contrôler le comportement spéculatif en empoisonnant le *Branch Target Buffer*. L'approche sature également le *Return Stack Buffer* afin de s'assurer que le comportement spéculatif est dirigé vers une boucle infinie.

Les concepteurs de microprocesseurs ont également proposé de nouvelles instructions permettant de contrôler la spéculation. Ainsi, sur l'architecture x86 IBRS (Indirect Branch Restricted Speculation) est un mode qui garantit que la spéculation sur les branchements ne peut être influencée par du code exécuté en dehors de ce mode. De même, STIBP (Single Thread Indirect Branch Prediction) permet de s'assurer que différents fils d'exécutions s'exécutant sur deux cœurs virtuels d'un même cœur logique ne partagent pas le *Branch Target Buffer*. L'instruction IBPB (Indirect Branch Predictor Barrier) permet de vider le *Branch Target Buffer*. Des instructions similaires sont disponibles sur l'architecture ARM. Ces différents mécanismes doivent être utilisés par le code de l'application ou de l'OS pour contrôler la spéculation.

Schwarz *et al.* proposent des modifications de la microarchitecture permettant de s'assurer que des données confidentielles ne peuvent être utilisées dans les exécutions transitoires [342]. Toutefois, cette approche nécessite des modifications dans la microarchitecture, l'OS, les compilateurs et les applications.

## Empêcher l'accès aux données sensibles

Une autre approche complémentaire consiste à empêcher le code exécuté de manière transitoire à accéder aux données sensibles.

Une première approche consiste à séparer le code des applications en différents composants et à isoler ces composants entre eux. En effet, dans les attaques de type Spectre, le code exécuté de manière spéculative respecte les frontières d'isolation.

Par exemple Google a isolé le traitement des différentes page Web consultées en parallèle dans les différents onglets de son navigateur Chrome [343]. L'isolation est réalisée en utilisant différents processus. Cette isolation permet également de limiter d'autres types d'attaques.

Une autre approche consiste à limiter le comportement du code exécuté spéculativement.
Ces approches permettent de limiter l'impact sur les performance mais elles ne sont pas robustes car d'autres motifs de code peuvent permettre de réaliser l'attaque.

Guarnieri *et al.* adoptent une approche conservatrice [340]. Ils analysent statiquement le code de l'application et essaient de prouver que l'exécution spéculative respecte une propriété de non-interférence. Dans le cas contraire, le branchement doit être protégé. L'analyse réalise une surapproximation, ce qui peut conduire à protéger plus de branchements que nécessaire. En revanche, les branchements vulnérables sont systématiquement protégés.

Afin de lutter contre les autres variantes de Spectre, des techniques ont également été proposées afin d'empêcher l'empoisonnement des *buffer* utilisés par le processeur pour la spéculation.

Ainsi, Google a proposé Retpoline [341], une solution purement logicielle contre les attaques Spectre-BTB. Elle consiste à remplacer, dans le code des applications, les branchements indirects par des retours de fonction, en ayant pris soin de pousser l'adresse du saut sur la pile. Le comportement spéculatif sur les retours de fonction étant contrôlé par le *Return Stack Buffer*, l'attaquant ne peut plus contrôler le comportement spéculatif en empoisonnant le *Branch Target Buffer*. L'approche sature également le *Return Stack Buffer* afin de s'assurer que le comportement spéculatif est dirigé vers une boucle infinie.

Les concepteurs de microprocesseurs ont également proposé de nouvelles instructions permettant de contrôler la spéculation. Ainsi, sur l'architecture x86 IBRS (Indirect Branch Restricted Speculation) est un mode qui garantit que la spéculation sur les branchements ne peut être influencée par du code exécuté en dehors de ce mode. De même, STIBP (Single Thread Indirect Branch Prediction) permet de s'assurer que différents fils d'exécutions s'exécutant sur deux cœurs virtuels d'un même cœur logique ne partagent pas le *Branch Target Buffer*. L'instruction IBPB (Indirect Branch Predictor Barrier) permet de vider le *Branch Target Buffer*. Des instructions similaires sont disponibles sur l'architecture ARM. Ces différents mécanismes doivent être utilisés par le code de l'application ou de l'OS pour contrôler la spéculation.

Schwarz *et al.* proposent des modifications de la microarchitecture permettant de s'assurer que des données confidentielles ne peuvent être utilisées dans les exécutions transitoires [342]. Toutefois, cette approche nécessite des modifications dans la microarchitecture, l'OS, les compilateurs et les applications.

## Empêcher l'accès aux données sensibles

Une autre approche complémentaire consiste à empêcher le code exécuté de manière transitoire à accéder aux données sensibles.

Une première approche consiste à séparer le code des applications en différents composants et à isoler ces composants entre eux. En effet, dans les attaques de type Spectre, le code exécuté de manière spéculative respecte les frontières d'isolation.

Par exemple Google a isolé le traitement des différentes page Web consultées en parallèle dans les différents onglets de son navigateur Chrome [343]. L'isolation est réalisée en utilisant différents processus. Cette isolation permet également de limiter d'autres types d'attaques.

Une autre approche consiste à limiter le comportement du code exécuté spéculativement.
Ainsi, Koruyeh et al. proposent d'utiliser le CFI pour limiter les attaques de type Spectre-BTB en empêchant les sauts vers des gadgets [344].

Une approche pour lutter contre les variantes de Spectre-PHT dues à un contrôle des bornes d'un pointeur consiste à utiliser un masquage du pointeur [345]. Toutefois, ce masquage est en général imprécis mais il fixe une limite sur la valeur du pointeur. Cela limite donc fortement la zone de mémoire que l'attaquant peut faire fuir. Une autre approche consiste à mettre en œuvre le *Speculative Load Hardening* proposé par LLVM [346].

### Supprimer ou limiter le canal caché
Certaines techniques utilisées pour limiter les canaux auxiliaires peuvent être utilisées pour limiter ou supprimer le canal caché, qui est la dernière étape de l'attaque.

Une approche plus globale consiste à supprimer le canal caché pour l'exécution spéculative [347, 348]. Cette solution consiste à utiliser une mémoire interne pour réaliser l'exécution spéculative, sans accéder au cache. Cette solution n'est toutefois pas implémentée dans les processeurs disponibles sur le marché.

### 2.3.3 Contre-mesures logicielles face aux attaques par martelle-ment de la mémoire

Des contre-mesures logicielles ont également été proposées pour lutter contre les attaques Rowhammer.

Les mesures proposées classiquement consistent à augmenter la vitesse de rafraîchissement de la DRAM et à empêcher l'attaquant d'exécuter l'instruction CLFLUSH permettant de vider le cache. Aweke et al. montrent que ces mesures ne sont pas suffisantes [349]. Ils réalisent en effet des attaques sans utiliser CLFLUSH, malgré le doublement de la fréquence de rafraîchissement. Ils proposent un mécanisme de défense qui surveille les accès mémoire fréquents à une adresse donnée et provoque un rafraîchissement des cellules mémoires adjacentes.

Brasser et al. s'intéressent plus particulièrement aux attaques visant le noyau de l'OS afin de réaliser une escalade de privilèges [350]. Ils proposent un mécanisme de défense spécifique à cette attaque qui confine l'attaquant de manière à ce qu'il ne puisse réaliser de changement d'état que dans l'espace mémoire qu'il contrôle déjà. Pour cela, les auteurs modifient le mécanisme d'allocation de la mémoire de l'OS afin de s'assurer que les pages de l'espace utilisateur correspondent à des adresses physiques qui ne permettent pas d'impacter les adresses physiques du noyau.

Konoth et al. généralisent ce principe. Ils intercallent des lignes de garde entre chaque ligne contenant des données dans la mémoire. Les lignes de garde absorbent les effets d'une attaque Rowhammer et évitent que les données, situées dans les lignes suivantes, soient affectées [351]. Van der Veen et al. utilisent la même approche pour protéger les *buffer* utilisés dans une attaque Rohammer utilisant le *DMA* sur l'architecture ARM [352].

RADAR est un projet qui permet de détecter toutes les formes d'attaques Rohammer en analysant les émissions électromagnétiques que produisent ces attaques [353]. Les auteurs
Ainsi, Koruyeh et al. proposent d'utiliser le CFI pour limiter les attaques de type Spectre-BTB en empêchant les sauts vers des gadgets [344].

Une approche pour lutter contre les variantes de Spectre-PHT dues à un contrôle des bornes d'un pointeur consiste à utiliser un masquage du pointeur [345]. Toutefois, ce masquage est en général imprécis mais il fixe une limite sur la valeur du pointeur. Cela limite donc fortement la zone de mémoire que l'attaquant peut faire fuir. Une autre approche consiste à mettre en œuvre le *Speculative Load Hardening* proposé par LLVM [346].

### Supprimer ou limiter le canal caché
Certaines techniques utilisées pour limiter les canaux auxiliaires peuvent être utilisées pour limiter ou supprimer le canal caché, qui est la dernière étape de l'attaque.

Une approche plus globale consiste à supprimer le canal caché pour l'exécution spéculative [347, 348]. Cette solution consiste à utiliser une mémoire interne pour réaliser l'exécution spéculative, sans accéder au cache. Cette solution n'est toutefois pas implémentée dans les processeurs disponibles sur le marché.

### 2.3.3 Contre-mesures logicielles face aux attaques par martelle-ment de la mémoire

Des contre-mesures logicielles ont également été proposées pour lutter contre les attaques Rowhammer.

Les mesures proposées classiquement consistent à augmenter la vitesse de rafraîchissement de la DRAM et à empêcher l'attaquant d'exécuter l'instruction CLFLUSH permettant de vider le cache. Aweke et al. montrent que ces mesures ne sont pas suffisantes [349]. Ils réalisent en effet des attaques sans utiliser CLFLUSH, malgré le doublement de la fréquence de rafraîchissement. Ils proposent un mécanisme de défense qui surveille les accès mémoire fréquents à une adresse donnée et provoque un rafraîchissement des cellules mémoires adjacentes.

Brasser et al. s'intéressent plus particulièrement aux attaques visant le noyau de l'OS afin de réaliser une escalade de privilèges [350]. Ils proposent un mécanisme de défense spécifique à cette attaque qui confine l'attaquant de manière à ce qu'il ne puisse réaliser de changement d'état que dans l'espace mémoire qu'il contrôle déjà. Pour cela, les auteurs modifient le mécanisme d'allocation de la mémoire de l'OS afin de s'assurer que les pages de l'espace utilisateur correspondent à des adresses physiques qui ne permettent pas d'impacter les adresses physiques du noyau.

Konoth et al. généralisent ce principe. Ils intercallent des lignes de garde entre chaque ligne contenant des données dans la mémoire. Les lignes de garde absorbent les effets d'une attaque Rowhammer et évitent que les données, situées dans les lignes suivantes, soient affectées [351]. Van der Veen et al. utilisent la même approche pour protéger les *buffer* utilisés dans une attaque Rohammer utilisant le *DMA* sur l'architecture ARM [352].

RADAR est un projet qui permet de détecter toutes les formes d'attaques Rohammer en analysant les émissions électromagnétiques que produisent ces attaques [353]. Les auteurs
utilisent pour cela un dispositif externe de radio logicielle (*Software Defined Radio*) leur permettant de faire l'acquisition des signaux.