Dans ce TD on va tenter de réaliser une attaque type 'Spectre' dans un environnement
contrôlé.
contrôlé.
Cette attaque exploite une vulnérabilité matérielle présente dans de nombreux processeurs
et permet de passer outre l'isolation intra et inter processus. Comme il s'agit d'une vulnérabilité
matérielle liée au design et au principe de fonctionnement des processeurs, il est assez difficile de
Cette attaque exploite une vulnérabilité matérielle présente dans de nombreux processeurs
et permet de passer outre l'isolation intra et inter processus. Comme il s'agit d'une vulnérabilité
matérielle liée au design et au principe de fonctionnement des processeurs, il est assez difficile de
s'en défendre, même si les fabricants de CPU y travaillent.
## Ce qu'on va voir
* Caches CPU
* Exécution 'out-of-order' et prédiction de branchement dans les CPU
* Exploitation du cache comme canal auxiliaire
* Vulnérabilité Spectre
* Caches CPU
* Exécution 'out-of-order' et prédiction de branchement dans les CPU
* Exploitation du cache comme canal auxiliaire
* Vulnérabilité Spectre
## Compilation des codes
...
...
@@ -26,13 +26,14 @@ Tous les codes devront être compilés comme suit :
```
## Utilisation du cache comme canal auxiliaire
Meltdown et Spectre utilisent le cache comme canal auxiliaire pour révéler un secret protégé. La technique utilisée est
Meltdown et Spectre utilisent le cache comme canal auxiliaire pour révéler un secret protégé. La technique utilisée est
dite FLUSH + RELOAD (vidage et rechargement). On va étudier cette technique en premier.
### Fonctions utiles
* Vider une ligne de cache : `_mm_clflush` ([doc intel](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_clflush))
* Lire le timestamp CPU : `__rdtscp` ([doc intel](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=__rdtscp))
* Vider une ligne de cache : `_mm_clflush` ([doc intel](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_clflush))
* Lire le timestamp CPU : `__rdtscp` ([doc intel](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=__rdtscp))
### Etape 1 : mesure du temps d'accès au cache
...
...
@@ -47,16 +48,17 @@ On se servira de ce seuil pour déterminer si une donnée est dans le cache ou n
Fichier à compléter / compiler : `flushreload.c`
L'idée est d'utiliser le temps d'accès au cache pour révéler un secret.
On suppose une fonction `victim` qui utilise le secret comme index pour accéder à un tableau. Ce secret est
On suppose une fonction `victim` qui utilise le secret comme index pour accéder à un tableau. Ce secret est
supposé inaccessible. La technique qu'on utilise pour révéler le secret manipulé par `victim` est appelée FLUSH+RELOAD.
1. Vider complètement le tableau de la mémoire cache
2. Appeler la victime. Cette action provoque le chargement dans le cache d'une ligne qui dépend du secret
3. Recharger le tableau dans le cache et mesurer le temps de rechargement de chaque élément. Si le temps est court, l'élément était déjà dans le cache et c'est cet élément que la victime a utilisé : on connaît alors le secret.
* Complétez `flushreload.c`
* Pourquoi pas simplement `array[256]` ?
* Pourquoi utiliser un décalage (rôle de `DELTA`) ?
* Est ce que la technique est fiable à 100% ? Pourquoi ?
1. Vider complètement le tableau de la mémoire cache
2. Appeler la victime. Cette action provoque le chargement dans le cache d'une ligne qui dépend du secret
3. Recharger le tableau dans le cache et mesurer le temps de rechargement de chaque élément. Si le temps est court, l'élément était déjà dans le cache et c'est cet élément que la victime a utilisé : on connaît alors le secret.
* Complétez `flushreload.c`
* Pourquoi pas simplement `array[256]` ?
* Pourquoi utiliser un décalage (rôle de `DELTA`) ?
* Est ce que la technique est fiable à 100% ? Pourquoi ?
## Exécution dans le désordre
...
...
@@ -67,34 +69,34 @@ pour maximiser le taux d'utilisation de ses unités de calcul (et donc maximiser
### Etape 3
1. Exécuter le programme (plusieurs fois). Qu'observez-vous ?
2. Ligne 67, remplacer par "`victim(i+20);`". Que se passe-t-il ? Pourquoi ? Remettez le code initial.
3. Commentez les lignes 66 et 71 (flush de la variable size). Est-ce que l'attaque fonctionne toujours ? Pourquoi ?
4. Décommentez les lignes 66 et 71.
1. Exécuter le programme (plusieurs fois). Qu'observez-vous ?
2. Ligne 66, remplacer par "`victim(i+20);`". Que se passe-t-il ? Pourquoi ? Remettez le code initial.
3. Commentez les lignes 65 et 70 (flush de la variable size). Est-ce que l'attaque fonctionne toujours ? Pourquoi ?
4. Décommentez les lignes 65 et 70.
## Attaque 'Spectre'
## Attaque 'Spectre'
Fichier à compléter / compiler : `spectreattack.c`
Dans ce code, on suppose une fonction `restrictedAccess` qui permet l'accès à un buffer limité pour simuler une sandbox.
Le secret est en dehors de la sandbox. L'accès au secret n'est possible qu'au travers de la fonction `restrictedAccess`
Dans ce code, on suppose une fonction `restrictedAccess` qui permet l'accès à un buffer limité pour simuler une sandbox.
Le secret est en dehors de la sandbox. L'accès au secret n'est possible qu'au travers de la fonction `restrictedAccess`
(c'est à dire qu'on a pas le droit de le lire directement). Le but est d'afficher le secret.
### Etape 4
### Etape 4
1. Exécutez le programme et déterminez si vous êtes capable de trouver la valeur secrète. Pourquoi le résultat n'est
pas fiable ? Exécutez le programme un nombre suffisant de fois pour être sûr du secret.
1. Exécutez le programme et déterminez si vous êtes capable de trouver la valeur secrète. Pourquoi le résultat n'est
pas fiable ? Exécutez le programme un nombre suffisant de fois pour être sûr du secret.
### Etape 5 : amélioration de la fiabilité de l'attaque.
### Etape 5 : amélioration de la fiabilité de l'attaque
Fichier à compléter / compiler : `spectreattackimproved.c`
Fichier à compléter / compiler : `spectreattackimproved.c`
L'idée est d'automatiser la répétition de l'attaque et de maintenir un tableau de scores pour chaque succès de cache.
C'est une approche statistique. Le secret est supposé être la valeur pour laquelle on a eu le plus de succès de cache.
L'idée est d'automatiser la répétition de l'attaque et de maintenir un tableau de scores pour chaque succès de cache.
C'est une approche statistique. Le secret est supposé être la valeur pour laquelle on a eu le plus de succès de cache.
1. Exécutez le programme. Qu'observez vous ?
2. Comment faire pour que le programme trouve réellement le secret qui n'est définitivement pas 0 ?
1. Exécutez le programme. Qu'observez vous ?
2. Comment faire pour que le programme trouve réellement le secret qui n'est définitivement pas 0 ?
### Etape 6 : détermination de tout le secret.
### Etape 6 : détermination de tout le secret
Modifiez `spectreattackimproved.c` pour qu'elle retourne tout le secret (toute la chaîne de caractère).
\ No newline at end of file
Modifiez `spectreattackimproved.c` pour qu'elle retourne tout le secret (toute la chaîne de caractère).