Skip to content
KitploitKITPLOIT
StrumentiBlog
Invia
StrumentiBlog
Invia

Strumenti di Hacking, PenTest e Cybersecurity per il tuo Arsenale di Sicurezza!

Kitploit è una directory di strumenti di hacking, cybersecurity e pentesting. Scopri gli ultimi aggiornamenti dei progetti per trovare vulnerabilità, analizzare sistemi, automatizzare i test e rafforzare la tua sicurezza.

··Feed·Contatto·Privacy·© 2026 Kitploit

Directory degli strumenti

Categorie

Vedi tutte le categorie
Loading categories
cve-2024-21978-poc — Exploit per la vulnerabilità del firmware AMD SEV-SNP CVE-2024-21978, che consente la decrittazione di memoria guest arbitraria tramite corruzione della memoria delle pagine di contesto. | Kitploit
Strumenti/GitHubGitHub/freax13/cve-2024-21978-poc
Strumenti di Crittografia/DecrittografiaMemory ForensicsAnalisi delle VulnerabilitàExploitPenetration TestingSicurezza HardwareBinary Exploitation
GitHubfreax13/cve-2024-21978-poc

cve-2024-21978-poc

Exploit per la vulnerabilità del firmware AMD SEV-SNP CVE-2024-21978, che consente la decrittazione di memoria guest arbitraria tramite corruzione della memoria delle pagine di contesto.

Vedi Repository
931 anno faNon ancora revisionato

Più Popolari

Vedi tutti →

Scopri gli strumenti più utilizzati dalla nostra community.

Esplora tutti gli strumenti

Sfoglia la nostra collezione di strumenti

Vedi tutti gli strumenti →
Condividi

Vulnerabilità del Firmware SEV

Questo repository contiene un exploit per una vulnerabilità nel firmware SEV. L'exploit permette di decifrare la memoria arbitraria di un guest SEV-SNP in esecuzione.

Testato sulla versione 1.55.16 (l'ultima al momento della scrittura).

Causa Principale

Il campo nv_paddr del comando SEV_INIT_EX può essere utilizzato per donare un blocco di memoria al firmware, in modo che possa essere usato al posto della memoria flash persistente. Se SEV-SNP è abilitato, questa memoria deve essere nello stato FIRMWARE. Il firmware verifica questo una sola volta durante l'esecuzione del comando SEV_INIT_EX. Da quel momento in poi, il firmware assume che questa memoria sia nello stato FIRMWARE e vi scrive senza ulteriori controlli.

L'assunzione che la memoria sia ancora nello stato FIRMWARE non è sempre corretta, nulla impedisce all'host di riportare lo stato a HYPERVISOR usando il comando SNP_PAGE_RECLAIM. Una volta che le pagine sono nello stato HYPERVISOR possono essere trasferite in altri stati, ad esempio CONTEXT. Anche se le pagine non sono più nello stato FIRMWARE, il firmware scriverà su di esse rompendo l'integrità richiesta da alcuni stati delle pagine.

Exploit

Possiamo sfruttare questa corruzione della memoria prendendo di mira le pagine CONTEXT. Le pagine CONTEXT sono un bersaglio potente, ma ci sono alcuni problemi:

  1. Le pagine CONTEXT sono crittografate con una chiave diversa rispetto alla memoria normale. Di conseguenza, non è facile controllare il testo in chiaro anche se potessimo controllare il crittogramma.
  2. Non abbiamo molto controllo sulla memoria scritta dal firmware.

La corruzione della memoria riempie effettivamente la pagina CONTEXT con dati casuali, quindi non è facile corrompere le pagine CONTEXT in modo utile per l'attaccante. Per aggirare questo, possiamo innescare ripetutamente il bug per causare corruzione e usare il comando SNP_GUEST_STATUS per leggere i campi rilevanti della pagina CONTEXT corrotta finché non osserviamo valori utili.

Il comando SNP_DBG_DECRYPT può essere utilizzato per decifrare la memoria di un guest SEV-SNP con la politica DEBUG abilitata. Se riusciamo a creare un CONTEXT in modo che abbia il flag DEBUG impostato e contenga l'ASID di un altro guest, possiamo usarlo per decifrare la memoria dell'altro guest anche se non ha la politica DEBUG impostata.

Risulta che SNP_DBG_DECRYPT ignori la maggior parte dei campi nella pagina CONTEXT, controlla solo gctx->guest.asid, gctx->guest.policy_snp e gctx->guest.guest_flags. La probabilità che questi campi siano corretti dopo la corruzione della memoria non è alta, ma non è nemmeno impossibile. La buona notizia è anche che possiamo leggere tutti questi campi usando il comando GUEST_STATUS.

In conclusione, possiamo sfruttare il bug con i seguenti passaggi:

  1. Transita nv_paddr nello stato FIRMWARE usando l'istruzione rmpupdate.
  2. Esegui il comando SEV_INIT_EX.
  3. Riporta nv_paddr nello stato HYPERVISOR usando il comando SNP_RECLAIM_PAGE.
  4. Crea una o più pagine CONTEXT all'indirizzo nv_paddr.
  5. Inganna il firmware per fargli scrivere su nv_paddr usando il comando SEV_PDH_GEN. Questo corrompe le pagine CONTEXT.
  6. Usa il comando GUEST_STATUS per verificare se SNP_DBG_DECRYPT avrebbe successo, altrimenti torna al passo 5. Il collo di bottiglia principale è che gli ASID sono memorizzati in un int a 32 bit, ma ci sono molti meno ASID validi (509 o 1006 a seconda della CPU), quindi ci vorranno parecchi tentativi per ottenere il risultato.

L'exploit passa la maggior parte del tempo nei passi 5 e 6. Le probabilità di ottenere tutte le condizioni giuste sono circa 1/20.000.000 su un EPYC Milan e possiamo fare circa 100 tentativi al secondo, quindi ci aspettiamo di ottenere le condizioni giuste circa una volta ogni due giorni (Attenzione: i calcoli sono solo approssimativi e potrei aver sbagliato qualcosa, ma aneddoticamente, una volta ogni due giorni sembra giusto). Possiamo accelerare il processo non attaccando una sola pagina CONTEXT alla volta, ma tre pagine CONTEXT a nv_paddr, nv_paddr+4096 e nv_paddr+8192 (SEV_PDH_GEN corromperà tre pagine). Fortunatamente questi passaggi possono essere eseguiti prima di avviare il guest vittima e devono avere successo una sola volta per attaccare un numero arbitrario di guest (nota che il PoC attualmente attacca un solo guest però).

Impatto

Anche se non ho ancora potuto testarlo, credo che una volta che un attaccante ha usato questa vulnerabilità per divulgare le chiavi di comunicazione della piattaforma della macchina virtuale del guest, possa inviare messaggi guest al firmware per conto del guest e usarli per richiedere report di attestazione. Ciò viola un principio chiave di SEV-SNP secondo cui solo il guest dovrebbe poter richiedere report di attestazione.

Mitigazione

Alcuni comandi (ad esempio SNP_RECLAIM_PAGE, SNP_GCTX_CREATE, RING_BUFFER, forse altri?, forse tutti per sicurezza?) che accettano una pagina FIRMWARE dovrebbero verificare se si sovrappone a nv_paddr e fallire in caso affermativo.

Mitigazioni di Aggiornamento

C'è un'altra preoccupazione che ho, di cui non sono sicuro se valida e mi piacerebbe sentire la vostra opinione: Se ho capito bene, il firmware SEV può essere aggiornato senza interrompere i guest in esecuzione. Questo mi suggerisce che sarebbe possibile trasferire la pagina CONTEXT corrotta da una vecchia versione vulnerabile del firmware a una nuova versione corretta. Sarebbe possibile iniziare con una versione più vecchia vulnerabile, eseguire l'exploit descritto sopra, aggiornare e impegnare il nuovo firmware corretto, avviare il guest con il nuovo firmware (in modo che la vecchia versione del firmware non appaia nel report di attestazione) e poi usare la pagina CONTEXT corrotta creata con il vecchio firmware per attaccare il guest creato con la nuova versione? Un consumatore dei report di attestazione creati dal nuovo guest sarebbe in grado di capire che la vecchia versione del firmware era in esecuzione in un certo momento prima che il nuovo guest fosse avviato? In caso contrario, sono necessarie ulteriori mitigazioni per evitare che ciò accada?

Utilizzo del PoC

  1. Applica le patch nella cartella linux-patches alla punta di https://github.com/AMDESE/linux/commits/snp-host-v10. Compila, installa e avvia il kernel.
  2. Esegui il PoC.
    root@kitploit:~
    root@server:~/sev-exploit# cargo run --release
        Finished release [optimized] target(s) in 0.12s
        Running `target/release/sev-exploit`
    Corrupt guest context page so that ASID is in range 1..510
    Smallest ASID: 0x0000001f iterations: 14052175 zeros: 10539628 unique asids: 31500727 elapsed time: 1d 19h 20m 31s
    Creating VM with same ASID
    [03, 00, 00, 00, 00, 00, 00, 00, 11, 0f, a0, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, f0, 51, a5, 03, 3f, 69, 6b, 93, e8, d8, 61, 0d, 2e, 5a, 45, f1, ea, 6d, bf, 49, fe, e4, a9, 2d, 8d, af, 76, 5e, 2e, 56, e0, fa, a9, b3, a7, e0, bc, 09, d9, 4f, 28, 5c, 9f, 84, d2, 7e, 34, eb, ea, 3f, 29, 88, 30, 01, 28, 65, 8b, 73, 3c, 84, 00, ae, 4a, 74, a2, 7a, d1, c7, 4f, 63, 7f, 72, 7b, 3b, 2f, 08, b3, 1a, 8c, 99, 1b, ad, b5, 1d, 42, 0b, 4d, 98, d4, 7d, c1, 0b, d6, 2f, b4, 6c, 6b, 51, a2, 92, 17, 3b, 01, e8, 82, 11, 1e, cb, cb, a2, 8f, c9, b0, 52, 1d, 1d, b7, d2, 25, 8d, 32, a9, 7a, 6f, 86, e4, 40, 44, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 80, 00, 88, 00, 00, 00, 00, ee, ff, 00, 00, f0, ff, ff, ff, ff, ff, ff, ff, ff, 3f, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, <cut off zeros>]
    thread 'main' panicked at src/main.rs:170:13:
    not yet implemented: use the leaked secrets to send guest messages
    note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
    

Nota che è normale che l'exploit funzioni per un periodo di tempo significativo (nell'ordine di ore se sei fortunato, giorni se non lo sei). Eseguirlo su un EPYC Genoa sarà probabilmente più veloce perché ci sono quasi il doppio di ASID validi.

Durante i passi 5 e 6, il PoC mostra alcune metriche:

  • "Smallest ASID": Il più piccolo ASID incontrato finora. Questa è solo una metrica di controllo per assicurarsi che incontriamo ASID sempre più piccoli nel tempo.
  • "iterations": Questa metrica viene incrementata ogni volta che il bug viene innescato.
  • "zeroes": In circa 1/4 dei casi, la pagina CONTEXT è in uno stato in cui il firmware considera che non abbia ancora un ASID assegnato. In quei casi SNP_GUEST_STATUS restituirà 0 nel campo ASID.
  • "unique asids": Un'altra metrica di controllo per assicurarsi che gli ASID siano casuali e non si ripetano dopo un po'.
  • "elapsed time": Durata dall'avvio del PoC.

Nella maggior parte dei casi, la dismissione delle pagine CONTEXT corrotte causa un crash del firmware (molto probabilmente qui). A quanto pare i crash del firmware causano un riavvio dell'intero sistema. Per evitare tali crash, le patch del kernel impediscono la dismissione delle pagine CONTEXT. Uno svantaggio di ciò è che il modulo del kernel ccp non può essere scaricato. Una volta avviato il PoC, l'intero sistema deve essere riavviato prima di poterlo riavviare (indipendentemente dal fatto che il PoC abbia avuto successo o sia stato interrotto).

Scarica lo strumento
  • Avvia (e opzionalmente esegui) un guest vittima usando l'ASID corrotto nella pagina CONTEXT corrotta. Tieni traccia della pagina dei segreti. Ciò è possibile perché il firmware SEV tiene traccia internamente degli ASID attivi e non controlla le pagine CONTEXT attive per verificare la presenza di duplicati.
  • Usa la pagina CONTEXT corrotta per eseguire SNP_DBG_DECRYPT sulla pagina dei segreti del guest vittima.