
Exploit para CVE-2024-21980 dirigido al firmware AMD SEV para descifrar memoria arbitraria de invitados SEV-SNP retirados mediante una omisión de la aplicación del búfer de comandos.
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 que haya sido dado de baja.
Probado en la versión 1.55.16 (la más reciente al momento de escribir esto).
El firmware SEV tiene una tabla llamada master_handler_table que contiene punteros a funciones para todos los comandos, junto con algunas propiedades adicionales relevantes para los comandos. Dos de esas propiedades adicionales son cmd_buf_type y snp_cmd_buf_enforcement. cmd_buf_type determina si el búfer de comandos debe copiarse desde y/o hacia la memoria del host. snp_cmd_buf_enforcement determina si estas operaciones de copia deben estar sujetas a comprobaciones que verifican que la memoria que respalda el búfer de comandos está en estado FIRMWARE o DEFAULT. Los comandos cuyo cmd_buf_type es CMD_BUF_OUTPUT_ONLY, CMD_BUF_INPUT_AND_OUTPUT o CMD_BUF_INPUT_AND_OUTPUT_ERROR deberían tener snp_cmd_buf_enforcement establecido en true. De lo contrario, la escritura de la salida del comando podría causar corrupción de memoria dentro del área cubierta por RMP. snp_cmd_buf_enforcement es true para todos estos comandos con una excepción: SEV_MCMD_ID_ATTESTATION: Este comando tiene cmd_buf_type establecido en CMD_BUF_INPUT_AND_OUTPUT_ERROR, pero también tiene snp_cmd_buf_enforcement establecido en false. Como resultado, es posible ejecutar SEV_MCMD_ID_ATTESTATION con un búfer de comandos que apunte a memoria cubierta por RMP y que esa memoria se corrompa una vez que se escriba la salida.
No veo por qué SEV_MCMD_ID_ATTESTATION necesitaría ser una excepción; me parece plausible que esto pueda ser un error tipográfico o de copiar y pegar.
SEV_MCMD_ID_ATTESTATION solo escribe en un único campo, length (4 bytes), del búfer de comandos, por lo que esos son los únicos bytes que podemos usar para corromper memoria. SEV_MCMD_ID_ATTESTATION siempre escribe el mismo valor: 0x000000d0. Afortunadamente, no hay requisitos de alineación para el búfer de comandos, por lo que podemos desplazar el búfer de comandos repetidamente para corromper un rango más amplio de memoria contigua. Usaremos esto para corromper los primeros 16 bytes de una página de contexto de invitado con un patrón estático. Esos primeros 16 bytes contienen la semilla de clave UMC y, al forzarla a un valor estático, podemos forzar que la clave de cifrado del invitado sea un valor estático.
El exploit proporcionado aquí se basa en gran medida en el que proporcioné para SWPSIRT-2684/CVE-2023-31355.
Para explotar la vulnerabilidad podemos ejecutar los siguientes pasos:
SEV_MCMD_ID_ATTESTATION. Mantener este invitado en ejecución.0x2000 para el invitado víctima. Cualquier otra dirección en el área cubierta por RMP también serviría, aunque una dirección fija es útil para depurar.0x2000 para el invitado atacante. Esta tiene que ser la misma dirección utilizada en el paso 1.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 de clave UMC.El impacto aquí debería ser al menos el mismo que con SWPSIRT-2684. No tengo claro en este momento si este error puede usarse para descifrar la memoria de un invitado en ejecución antes de que haya sido dado de baja.
snp_cmd_buf_enforcement debería establecerse en true para SEV_MCMD_ID_ATTESTATION.
Curiosamente, los parches de soporte del host KVM de Linux no necesitan actualizarse porque ya enumeran SEV_CMD_ATTESTATION_REPORT en sev_cmd_buf_writable como un comando que requiere que su búfer de comandos esté en estado FIRMWARE. Puede que se necesiten cambios o no para otros hipervisores.