
Reproduction de l'attaque micro-architecturale Retbleed (CVE-2022-29900/29901) dans gem5. Sous-dépassement du RSB, fuite par canal auxiliaire Flush+Reload et une mitigation lfence vérifiée.
Une reproduction pratique de Retbleed (CVE-2022-29900 / CVE-2022-29901) — l'attaque micro-architecturale de 2022 qui a brisé la défense « Retpoline » en prouvant que les instructions ret, longtemps considérées comme sûres, peuvent être détournées lorsque le Return Stack Buffer (RSB) du CPU sous-déborde.
Ce projet simule le cycle de vie complet de l'attaque sur un modèle de CPU x86 Out-of-Order dans gem5 : déclencher un sous-dépassement du RSB, exfiltrer des données secrètes octet par octet via un canal auxiliaire de cache Flush+Reload, puis vérifier une contre-mesure logicielle (lfence) qui colmate la fuite.
Projet de cours — Advanced Computer Architecture, Automne 2025, CUNY City College Auteurs : Abdul Kalam Mansoor & Rebiha Selmani
Les attaques de type Spectre ont montré que l'exécution spéculative laisse des effets de bord au niveau du cache même lorsque le CPU « annule » une mauvaise prédiction. Le correctif de l'industrie — Retpoline — remplaçait les sauts indirects dangereux par des instructions ret, en supposant que les retours sont prédits de manière sûre à partir d'une petite pile matérielle (le RSB). Retbleed a montré que cette hypothèse est fausse : épuisez le RSB par une récursion profonde, et le CPU retombe silencieusement sur le même prédicteur dangereux que Retpoline était censé éviter.
| Étape | Ce qui se passe |
|---|---|
| 1. Déclenchement | rsb_deep_call() récurse sur 32 niveaux de profondeur, débordant le RSB de 16 entrées. Lorsque la récursion se déroule, le RSB est vide. |
| 2. Repli | Le RSB étant vide, le CPU se replie sur le Branch Target Buffer (BTB) pour prédire la cible du ret — que l'attaquant peut empoisonner. |
| 3. Gadget | Le chemin spéculatif détourné exécute gadget(), qui lit un octet du mot de passe secret et l'utilise pour indexer dans probe_array, tirant une page de ce tableau dans le cache. |
| 4. Espion Flush+Reload | Avant l'attaque, chaque page de probe_array est vidée du cache (_mm_clflush). Une fois la fenêtre spéculative refermée, le programme chronomètre l'accès à chaque valeur d'octet possible (__rdtscp) — celle qui revient rapidement (succès de cache) révèle l'octet secret. |
Répéter cela pour chaque octet de ROOT_PASSWORD reconstruit tout le secret sans jamais appeler gadget() au niveau architectural.
| Mode | Latence d'accès | Résultat |
|---|---|---|
Vulnérable (SECURE_MODE non défini) | ~49 cycles (succès de cache) | Secret exfiltré octet par octet, confirmé par les indicateurs rouges HIT! |
Corrigé (SECURE_MODE défini, _mm_lfence() injecté) | >150 cycles (échec de cache / bruit) | L'attaque échoue — la sortie affiche SAFE / Found: ??? |
Le lfence force le CPU à résoudre l'adresse de retour avant que toute instruction suivante puisse s'exécuter, réduisant la fenêtre spéculative avant que le gadget ne touche à la mémoire dépendante du secret.
src/
retbleed.c # Full PoC: trigger, gadget, Flush+Reload spy, and lfence mitigation (toggle via SECURE_MODE)
docs/
Retbleed_Report.pdf # Full written report: methodology, related work, gem5 setup, results
Retbleed_Attack_Demonstration.pptx # Slide deck used to present the project
Le PoC a été compilé et mesuré sous gem5 (DerivO3CPU, un modèle out-of-order — nécessaire car les modèles in-order n'implémentent pas l'exécution spéculative) :
gcc -O0 -static -o retbleed src/retbleed.c
./build/X86/gem5.opt configs/deprecated/example/se.py \
--cpu-type=DerivO3CPU --caches --l2cache \
--l1d_size=64kB --l1i_size=64kB --cmd=retbleed
Pour basculer entre le comportement vulnérable et corrigé, commentez/décommentez cette ligne en haut de retbleed.c :
#define SECURE_MODE
Le code utilise de véritables intrinsics x86 (
_mm_clflush,__rdtscp,_mm_lfence) et peut aussi être compilé et exécuté nativement sur du matériel x86 (gcc -O0 -o retbleed src/retbleed.c) pour une démonstration plus rapide — les résultats varieront selon les propres contre-mesures du CPU hôte (eIBRS, correctifs de microcode, etc.), ce qui illustre en soi à quel point cette classe de bug a été corrigée depuis 2022.
lfence supplémentaires) mesurées à 14–39 % de surcoût de performance sur le matériel affecté.