
Exploit para la vulnerabilidad de firmware AMD SEV-SNP (CVE-2023-31355) que descifra memoria arbitraria de invitados dados de baja corrompiendo la semilla de clave UMC mediante una escritura de entrada RMP no inicializada a la dirección cero.
Este repositorio contiene un exploit para una vulnerabilidad en el firmware SEV. El exploit permite descifrar memoria arbitraria de un invitado SEV-SNP después de haber sido dado de baja.
Probado en la versión 1.55.16 (la más reciente al momento de escribir).
snp_reclaim_buffer intenta incondicionalmente escribir de vuelta los cambios del RMP incluso cuando la dirección no está cubierta por el RMP. Si address no está cubierta por el RMP, la dirección para la entrada RMP page_rmp_paddr nunca se inicializa correctamente y permanece en su valor inicial de 0. Como resultado, el firmware intenta escribir los cambios a la entrada RMP de vuelta a la dirección 0. Esto es malo porque la dirección 0 está cubierta por el RMP y no debería escribirse sin más comprobaciones. Si address está fuera del área cubierta por el RMP, page_rmp_entry nunca se inicializa correctamente y contiene basura de la pila. Esta basura es constante en la práctica.
Hay un comentario advirtiendo exactamente sobre este patrón de código, que también es por lo que no me sorprendería si no soy el primero en reportar esto.
snp_reclaim_buffer es llamado con la dirección de la página de estado de los búferes de anillo SEV cuando el hipervisor solicita salir del modo de búfer de anillo. Esta dirección es controlada por el atacante. Hay algunas comprobaciones para esta dirección, pero las páginas predeterminadas (es decir, páginas fuera del área cubierta por el RMP) están explícitamente permitidas.
Podemos explotar esta escritura en la dirección 0 colocando una página de contexto de invitado allí. Convenientemente, el primer campo de la página de contexto de invitado es la semilla clave UMC, que tiene exactamente el mismo tamaño que una entrada RMP (ambas tienen 16 bytes de tamaño). Engañando al firmware para que escriba los cambios de vuelta a la dirección 0, podemos corromper la semilla clave UMC. La entrada RMP no inicializada que se escribe es siempre la misma, por lo que la semilla clave UMC corrompida también será casi siempre la misma: el conteo de subpáginas (9 bits) en la entrada RMP no se escribe, pero todos los demás campos sí. Al crear repetidamente nuevas páginas de contexto de invitado que tendrán un conteo de subpáginas inicial aleatorio diferente cada vez, podemos eventualmente crear múltiples invitados con la misma semilla clave UMC.
Para explotar la vulnerabilidad podemos ejecutar los siguientes pasos:
0 para el invitado víctima.0 para el invitado atacante.SNP_DBG_ENCRYPT para descifrar la memoria del invitado víctima usando la página de contexto del invitado atacante. Esto tendrá éxito porque el invitado víctima y el invitado atacante comparten una semilla clave UMC.Debido al hecho de que solo podemos descifrar memoria después de que el invitado haya sido dado de baja, no es posible crear informes de atestación falsificados aunque tengamos acceso a los secretos del invitado. Solo podemos crear informes de atestación falsificados si el invitado ha sido migrado a otro host antes de ser dado de baja: en este caso, los secretos (es decir, VMPCKs) del invitado dado de baja también funcionarán en la nueva instancia migrada.
En la práctica, sin embargo, muchas aplicaciones almacenan otra información sensible (es decir, claves privadas, claves de cifrado de disco) que pueden filtrarse usando este exploit.
La entrada RMP solo debe escribirse de vuelta si la página no estaba en el estado predeterminado.