
Exploit für AMD SEV-SNP-Firmware-Schwachstelle (CVE-2023-31355), die beliebigen Speicher von stillgelegten Gästen entschlüsselt, indem der UMC-Key-Seed über einen nicht initialisierten RMP-Eintrag-Schreibvorgang an Adresse Null beschädigt wird.
Dieses Repository enthält einen Exploit für eine Schwachstelle in der SEV-Firmware. Der Exploit ermöglicht es, beliebigen Speicher eines SEV-SNP-Gasts zu entschlüsseln, nachdem dieser dekommissioniert wurde.
Getestet mit Version 1.55.16 (zum Zeitpunkt des Schreibens die neueste Version).
snp_reclaim_buffer unternimmt bedingungslos den Versuch, RMP-Änderungen zurückzuschreiben, selbst wenn die Adresse nicht vom RMP abgedeckt ist. Wenn address nicht vom RMP abgedeckt ist, wird die Adresse für den RMP-Eintrag page_rmp_paddr nie ordnungsgemäß initialisiert und bleibt bei ihrem Anfangswert 0. Infolgedessen versucht die Firmware, die Änderungen am RMP-Eintrag an Adresse 0 zurückzuschreiben. Das ist problematisch, weil Adresse 0 vom RMP abgedeckt ist und ohne weitere Prüfungen nicht beschrieben werden sollte. Wenn address außerhalb des vom RMP abgedeckten Bereichs liegt, wird page_rmp_entry nie ordnungsgemäß initialisiert und enthält Speichermüll vom Stack. Dieser Speichermüll ist in der Praxis konstant.
Es gibt einen Kommentar, der vor genau diesem Codemuster warnt; auch deshalb würde es mich nicht überraschen, wenn ich nicht der Erste bin, der das meldet.
snp_reclaim_buffer wird mit der Adresse der Statusseite der SEV-Ringpuffer aufgerufen, wenn der Hypervisor das Verlassen des Ringpuffermodus anfordert. Diese Adresse ist vom Angreifer kontrolliert. Es gibt einige Prüfungen für diese Adresse, aber Standardseiten (d. h. Seiten außerhalb des vom RMP abgedeckten Bereichs) sind explizit erlaubt.
Wir können dieses Schreiben an Adresse 0 ausnutzen, indem wir dort eine Gastkontextseite platzieren. Praktischerweise ist das erste Feld der Gastkontextseite der UMC-Schlüssel-Seed, der genau so groß ist wie ein RMP-Eintrag (beide sind 16 Bytes groß). Indem wir die Firmware dazu bringen, Änderungen an Adresse 0 zurückzuschreiben, können wir den UMC-Schlüssel-Seed korrumpieren. Der nicht initialisierte RMP-Eintrag, der geschrieben wird, ist immer derselbe, sodass auch der korrumpierte UMC-Schlüssel-Seed immer fast derselbe sein wird: Die Subpage-Anzahl (9 Bits) im RMP-Eintrag wird nicht geschrieben, aber alle anderen Felder schon. Indem wir wiederholt neue Gastkontextseiten erstellen, die jedes Mal eine andere zufällige anfängliche Subpage-Anzahl haben, können wir schließlich mehrere Gäste mit demselben UMC-Schlüssel-Seed erstellen.
Um die Schwachstelle auszunutzen, können wir die folgenden Schritte ausführen:
0 für den Opfer-Gast.0 für den Angreifer-Gast.SNP_DBG_ENCRYPT, um den Speicher des Opfer-Gasts mithilfe der Kontextseite des Angreifer-Gasts zu entschlüsseln. Dies wird gelingen, weil der Opfer-Gast und der Angreifer-Gast einen gemeinsamen UMC-Schlüssel-Seed verwenden.Da wir den Speicher erst entschlüsseln können, nachdem der Gast dekommissioniert wurde, ist es nicht möglich, gefälschte Attestierungsberichte zu erstellen, obwohl wir Zugriff auf die Geheimnisse des Gasts haben. Wir können nur dann gefälschte Attestierungsberichte erstellen, wenn der Gast vor der Dekommissionierung auf einen anderen Host migriert wurde: In diesem Fall funktionieren die Geheimnisse (d. h. VMPCKs) des dekommissionierten Gasts auch auf der neu migrierten Instanz.
In der Praxis speichern viele Anwendungen jedoch andere sensible Informationen (z. B. private Schlüssel, Festplattenverschlüsselungsschlüssel), die mit diesem Exploit geleakt werden können.
Der RMP-Eintrag sollte nur dann zurückgeschrieben werden, wenn sich die Seite nicht im Standardzustand befand.