
Exploit pour la vulnérabilité du firmware AMD SEV-SNP (CVE-2023-31355) qui déchiffre la mémoire arbitraire d'invités décommissionnés en corrompant la graine de clé UMC via une écriture non initialisée d'entrée RMP à l'adresse zéro.
Ce dépôt contient un exploit pour une vulnérabilité dans le firmware SEV. L'exploit permet de déchiffrer la mémoire arbitraire d'un invité SEV-SNP après qu'il a été décommissionné.
Testé sur la version 1.55.16 (dernière version au moment de la rédaction).
snp_reclaim_buffer tente sans condition de réécrire les modifications RMP même lorsque l'adresse n'est pas couverte par la RMP. Si address n'est pas couverte par la RMP, l'adresse de l'entrée RMP page_rmp_paddr n'est jamais correctement initialisée et reste à sa valeur initiale de 0. En conséquence, le firmware tente de réécrire les modifications de l'entrée RMP à l'adresse 0. C'est problématique car l'adresse 0 est couverte par la RMP et ne devrait pas être écrite sans vérifications supplémentaires. Si address est en dehors de la zone couverte par la RMP, page_rmp_entry n'est jamais correctement initialisé et contient de la mémoire parasite provenant de la pile. Cette mémoire parasite est en pratique constante.
Il y a un commentaire qui met en garde contre exactement ce modèle de code, ce qui explique aussi pourquoi je ne serais pas surpris de ne pas être le premier à le signaler.
snp_reclaim_buffer est appelé avec l'adresse de la page de statut des tampons en anneau SEV lorsque l'hyperviseur demande la sortie du mode tampon en anneau. Cette adresse est contrôlée par l'attaquant. Il y a quelques vérifications pour cette adresse, mais les pages par défaut (c.-à-d. les pages en dehors de la zone couverte par la RMP) sont explicitement autorisées.
Nous pouvons exploiter cette écriture à l'adresse 0 en y plaçant une page de contexte d'invité. Par commodité, le premier champ de la page de contexte d'invité est la UMC key seed, dont la taille est exactement identique à celle d'une entrée RMP (les deux font 16 octets). En trompant le firmware pour qu'il réécrive les modifications à l'adresse 0, nous pouvons corrompre la UMC key seed. L'entrée RMP non initialisée qui est écrite est toujours la même, donc la UMC key seed corrompue sera également presque toujours la même : le nombre de sous-pages (9 bits) de l'entrée RMP n'est pas écrit, mais tous les autres champs le sont. En créant à plusieurs reprises de nouvelles pages de contexte d'invité qui auront à chaque fois des nombres de sous-pages initiaux aléatoires différents, nous pouvons à terme créer plusieurs invités avec la même UMC key seed.
Pour exploiter la vulnérabilité, nous pouvons exécuter les étapes suivantes :
0 pour l'invité victime.0 pour l'invité attaquant.SNP_DBG_ENCRYPT pour déchiffrer la mémoire de l'invité victime en utilisant la page de contexte de l'invité attaquant. Cette opération réussira car l'invité victime et l'invité attaquant partagent une UMC key seed.Étant donné que nous ne pouvons déchiffrer la mémoire qu'après que l'invité a été décommissionné, il n'est pas possible de créer de faux rapports d'attestation, même si nous avons accès aux secrets de l'invité. Nous ne pouvons créer de faux rapports d'attestation que si l'invité a été migré vers un autre hôte avant d'être décommissionné : dans ce cas, les secrets (c.-à-d. les VMPCKs) de l'invité décommissionné fonctionneront également sur la nouvelle instance migrée.
En pratique cependant, beaucoup d'applications stockent d'autres informations sensibles (c.-à-d. des clés privées, des clés de chiffrement de disque) qui peuvent être divulguées à l'aide de cet exploit.
L'entrée RMP ne devrait être réécrite que si la page n'était pas dans l'état par défaut.