
Riproduzione dell'attacco micro-architetturale Retbleed (CVE-2022-29900/29901) in gem5. Underflow dell'RSB, leak side-channel Flush+Reload e una mitigazione lfence verificata.
Una riproduzione pratica di Retbleed (CVE-2022-29900 / CVE-2022-29901) — l'attacco micro-architetturale del 2022 che ha infranto la difesa "Retpoline" dimostrando che le istruzioni ret, da lungo tempo considerate sicure, possono essere dirottate quando il Return Stack Buffer (RSB) della CPU va in underflow.
Questo progetto simula l'intero ciclo di vita dell'attacco su un modello di CPU x86 Out-of-Order in gem5: innescando un RSB underflow, sottraendo dati segreti un byte alla volta attraverso un canale laterale della cache Flush+Reload, e infine verificando una mitigazione software (lfence) che chiude la falla.
Progetto di corso — Advanced Computer Architecture, Autunno 2025, CUNY City College Autori: Abdul Kalam Mansoor & Rebiha Selmani
Gli attacchi in stile Spectre hanno dimostrato che l'esecuzione speculativa lascia effetti collaterali a livello di cache anche quando la CPU "annulla" una previsione errata. La soluzione dell'industria — Retpoline — sostituiva i pericolosi salti indiretti con istruzioni ret, presupponendo che i ritorni fossero previsti in modo sicuro da un piccolo stack hardware (l'RSB). Retbleed ha dimostrato che tale presupposto è falso: esaurisci l'RSB con una ricorsione profonda, e la CPU ricade silenziosamente sullo stesso predittore insicuro che Retpoline era progettato per evitare.
| Fase | Cosa accade |
|---|---|
| 1. Trigger | rsb_deep_call() ricorre per 32 livelli di profondità, saturando l'RSB a 16 entry. Quando la ricorsione si srotola, l'RSB è vuoto. |
| 2. Fallback | Con l'RSB vuoto, la CPU ricade sul Branch Target Buffer (BTB) per prevedere il target della ret — che un attaccante può avvelenare. |
| 3. Gadget | Il percorso speculativo dirottato esegue gadget(), che legge un byte della password segreta e lo usa per indicizzare probe_array, portando una pagina di quell'array nella cache. |
| 4. Spia Flush+Reload | Prima dell'attacco, ogni pagina di probe_array viene svuotata dalla cache (_mm_clflush). Dopo la chiusura della finestra speculativa, il programma misura il tempo di accesso per ogni possibile valore di byte (__rdtscp) — quello che ritorna veloce (cache hit) rivela il byte segreto. |
Ripetendo questo per ogni byte di ROOT_PASSWORD si ricostruisce l'intero segreto senza mai chiamare architetturalmente gadget().
| Modalità | Latenza di accesso | Esito |
|---|---|---|
Vulnerabile (SECURE_MODE non definito) | ~49 cicli (cache hit) | Segreto sottratto byte per byte, confermato dagli indicatori rossi HIT! |
Corretta (SECURE_MODE definito, _mm_lfence() iniettata) | >150 cicli (cache miss / rumore) | Attacco fallito — l'output mostra SAFE / Found: ??? |
La lfence forza la CPU a risolvere l'indirizzo di ritorno prima che qualsiasi istruzione successiva possa essere eseguita, collassando la finestra speculativa prima che il gadget tocchi mai memoria dipendente dal segreto.
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
Il PoC è stato compilato e misurato sotto gem5 (DerivO3CPU, un modello out-of-order — necessario perché i modelli in-order non implementano l'esecuzione speculativa):
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
Per passare tra comportamento vulnerabile e corretto, commentare/decommentare questa riga in cima a retbleed.c:
#define SECURE_MODE
Il codice utilizza intrinsics x86 reali (
_mm_clflush,__rdtscp,_mm_lfence) e può anche essere compilato ed eseguito nativamente su hardware x86 (gcc -O0 -o retbleed src/retbleed.c) per una demo più rapida — i risultati varieranno in base alle mitigazioni della CPU host (eIBRS, patch del microcodice, ecc.), il che è di per sé un'utile illustrazione di quanto a fondo questa classe di bug sia stata corretta dal 2022.
lfence aggiuntive) hanno misurato un overhead prestazionale del 14–39% sull'hardware interessato.