
Exploit para vulnerabilidade de firmware AMD SEV-SNP (CVE-2023-31355) que descriptografa memória arbitrária de convidados descomissionados ao corromper a semente de chave UMC através de uma escrita de entrada RMP não inicializada no endereço zero.
Este repositório contém um exploit para uma vulnerabilidade no firmware SEV. O exploit permite descriptografar memória arbitrária de um convidado SEV-SNP após sua descomissionamento.
Testado na versão 1.55.16 (mais recente no momento da escrita).
snp_reclaim_buffer tenta incondicionalmente escrever de volta as alterações do RMP mesmo quando o endereço não é coberto pelo RMP. Se address não é coberto pelo RMP, o endereço da entrada RMP page_rmp_paddr nunca é inicializado adequadamente e permanece em seu valor inicial de 0. Como resultado, o firmware tenta escrever as alterações da entrada RMP de volta ao endereço 0. Isso é ruim porque o endereço 0 é coberto pelo RMP e não deve ser escrito sem mais verificações. Se address está fora da área coberta pelo RMP, page_rmp_entry nunca é inicializado adequadamente e contém lixo de memória da pilha. Esse lixo de memória é constante na prática.
Há um comentário alertando exatamente sobre esse padrão de código, o que também é o motivo pelo qual não me surpreenderia se eu não for o primeiro a relatar isso.
snp_reclaim_buffer é chamado com o endereço da página de status dos buffers de anel SEV quando o hipervisor solicita a saída do modo de buffer de anel. Este endereço é controlado pelo atacante. Existem algumas verificações para este endereço, mas páginas padrão (ou seja, páginas fora da área coberta pelo RMP) são explicitamente permitidas.
Podemos explorar essa escrita no endereço 0 colocando uma página de contexto do convidado lá. Convenientemente, o primeiro campo da página de contexto do convidado é a semente da chave UMC, que tem exatamente o mesmo tamanho de uma entrada RMP (ambos têm 16 bytes). Ao enganar o firmware para escrever alterações de volta ao endereço 0, podemos corromper a semente da chave UMC. A entrada RMP não inicializada que é escrita é sempre a mesma, então a semente da chave UMC corrompida também será sempre quase a mesma: A contagem de subpáginas (9 bits) na entrada RMP não é escrita, mas todos os outros campos são. Ao criar repetidamente novas páginas de contexto do convidado, que terão contagens iniciais de subpáginas aleatórias diferentes a cada vez, podemos eventualmente criar vários convidados com a mesma semente de chave UMC.
Para explorar a vulnerabilidade, podemos executar as seguintes etapas:
0 para o convidado vítima.0 para o convidado atacante.SNP_DBG_ENCRYPT para descriptografar a memória do convidado vítima usando a página de contexto do convidado atacante. Isso terá sucesso porque o convidado vítima e o convidado atacante compartilham uma semente de chave UMC.Devido ao fato de que só podemos descriptografar a memória após o convidado ter sido descomissionado, não é possível criar relatórios de atestação falsificados, mesmo que tenhamos acesso aos segredos do convidado. Só podemos criar relatórios de atestação falsificados se o convidado tiver sido migrado para outro host antes do descomissionamento: Nesse caso, os segredos (ou seja, VMPCKs) do convidado descomissionado também funcionarão na nova instância migrada.
Na prática, no entanto, muitos aplicativos armazenam outras informações sensíveis (ou seja, chaves privadas, chaves de criptografia de disco) que podem ser vazadas usando este exploit.
A entrada RMP só deve ser escrita de volta se a página não estiver no estado padrão.