
Exploit for AMD SEV-SNP firmware vulnerability (CVE-2023-31355) that decrypts arbitrary memory of decommissioned guests by corrupting the UMC key seed via an uninitialized RMP entry write to address zero.
This repo contains an exploit for a vulnerability in the SEV firmware. The exploit allows decrypting arbitrary memory of an SEV-SNP guest after it's been decommissioned.
Tested on version 1.55.16 (latest as of time of writing).
snp_reclaim_buffer unconditionally tries to write back RMP changes even when the address isn't covered by the RMP. If address is not covered by the RMP, the address for the RMP entry page_rmp_paddr is never properly initialized and stays at its initial value of 0. As a result the firmware tries to write the changes to the RMP entry back to address 0. This is bad because address 0 is covered by the RMP and shouldn't be written to without more checks. If address is outside the RMP covered area, page_rmp_entry is never properly initialized and contains garbage memory from the stack. This garbage memory is constant in practice.
There's a comment warning about exactly this code pattern, which is also why I wouldn't be surprised if I'm not the first one to report this.
snp_reclaim_buffer is called with the address of the status page of the SEV ring buffers when the hypervisor requests exiting ring buffer mode. This address is attacker controlled. There are some checks for this address, but default pages (i.e. pages outside the RMP covered area) are explicitly allowed.
We can exploit this write to address 0 by placing a guest context page there. Conveniently the first field of the guest context page is the UMC key seed which is exactly the same size as an RMP entry (both are 16 bytes in size). By tricking the firmware into writing changes back to address 0 we can corrupt the UMC key seed. The uninitialized RMP entry that is written is always the same, so the corrupted UMC key seed will also always be almost the same: The subpage count (9 bits) in the RMP entry is not written, but all other fields are. By repeatedly creating new guest context pages which will have a different random initial subpage counts each time, we can eventually create multiple guests with the same UMC key seed.
To exploit the vulnerability we can execute the following steps:
0 for the victim guest.0 for the attacker guest.SNP_DBG_ENCRYPT command to decrypt the victim guest's memory using the attacker guest's context page. This will succeed because the victim guest and the attacker guest share a UMC key seed.Due to the fact that we can only decrypt memory after the guest has been decommissioned, it's not possible to create counterfeit attestation reports even though we have access to the guest's secrets. We can only create counterfeit attestation reports if the guest has been migrated to another host before decomissioned: In this case the secrets (i.e. VMPCKs) from the decomissioned guest will also work on the new migrated instance.
In practice though, a lot of applications store other sensitive information (i.e. private keys, disk encryption keys) that can be leaked using this exploit.
The RMP entry should only be written back if the page was not in the default state.